つまり、Swiftで「純粋な仮想関数」を作成する標準的な方法はありますか。その一つすべてのサブクラスによってオーバーライドされなければならないあり、オーバーライドされていない場合は、コンパイル時にエラーが発生します。
protocol
(と比べてS interface
あなたが抽象メソッドのようにそれらを使用する必要がある場合は、Javaでの)この質問/答えを見てきた:stackoverflow.com/a/39038828/2435872
つまり、Swiftで「純粋な仮想関数」を作成する標準的な方法はありますか。その一つすべてのサブクラスによってオーバーライドされなければならないあり、オーバーライドされていない場合は、コンパイル時にエラーが発生します。
protocol
(と比べてS interface
あなたが抽象メソッドのようにそれらを使用する必要がある場合は、Javaでの)この質問/答えを見てきた:stackoverflow.com/a/39038828/2435872
回答:
次の2つのオプションがあります。
スーパークラスをクラスではなくプロトコルとして定義する
Pro:各「サブクラス」(実際のサブクラスではない)が必要なメソッドを実装しているかどうかのコンパイル時間チェック
コン:「スーパークラス」(プロトコル)はメソッドやプロパティを実装できません
例:
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
プロ:スーパークラスでメソッドとプロパティを実装できます
短所:コンパイル時のチェックなし
fatalError
、コンパイル時のチェックを提供していない、それはコンパイラが少なくともスマート十分でメソッドの実行パスの呼び出しの戻り値を提供する必要がないであることがいいですfatalError
。
super.someFunc()
オーバーライドされたメソッドから呼び出した場合、オーバーライドしたにもかかわらずエラーが発生することに注意してください。あなたはそれを呼び出すことを想定していないことを知っていますが、他の誰かがそれを知っている必要はなく、標準的な慣習に従うだけです。
以下は、クラスからの継承と、プロトコルのコンパイル時チェックを可能にします:)
protocol ViewControllerProtocol {
func setupViews()
func setupConstraints()
}
typealias ViewController = ViewControllerClass & ViewControllerProtocol
class ViewControllerClass : UIViewController {
override func viewDidLoad() {
self.setup()
}
func setup() {
guard let controller = self as? ViewController else {
return
}
controller.setupViews()
controller.setupConstraints()
}
//.... and implement methods related to UIViewController at will
}
class SubClass : ViewController {
//-- in case these aren't here... an error will be presented
func setupViews() { ... }
func setupConstraints() { ... }
}
抽象クラス/仮想関数はサポートされていませんが、ほとんどの場合、プロトコルを使用できます。
protocol SomeProtocol {
func someMethod()
}
class SomeClass: SomeProtocol {
func someMethod() {}
}
SomeClassがsomeMethodを実装していない場合、次のコンパイル時エラーが発生します。
error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
「仮想」メソッドが多すぎない場合の別の回避策は、サブクラスに「実装」を関数オブジェクトとして基本クラスコンストラクターに渡させることです。
class MyVirtual {
// 'Implementation' provided by subclass
let fooImpl: (() -> String)
// Delegates to 'implementation' provided by subclass
func foo() -> String {
return fooImpl()
}
init(fooImpl: (() -> String)) {
self.fooImpl = fooImpl
}
}
class MyImpl: MyVirtual {
// 'Implementation' for super.foo()
func myFoo() -> String {
return "I am foo"
}
init() {
// pass the 'implementation' to the superclass
super.init(myFoo)
}
}
答えで提案されているようにあなたはアサーション対プロトコルを使用することができ、ここでdrewag
。ただし、プロトコルの例はありません。ここでカバーします
protocol SomeProtocol {
func someMethod()
}
class SomeClass: SomeProtocol {
func someMethod() {}
}
現在、すべてのサブクラスは、コンパイル時にチェックされるプロトコルを実装する必要があります。SomeClassがsomeMethodを実装していない場合、次のコンパイル時エラーが発生します。
エラー:タイプ「SomeClass」はプロトコル「SomeProtocol」に準拠していません
注:これは、プロトコルを実装する最上位のクラスでのみ機能します。すべてのサブクラスは、プロトコル要件を簡単に無視できます。– によるコメントmemmons
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
ただし、アサーションは実行時にのみ機能します。
iOS開発の初心者なので、いつ実装されたのかは完全にはわかりませんが、両方の利点を最大限に活用する1つの方法は、プロトコルの拡張機能を実装することです。
protocol ThingsToDo {
func doThingOne()
}
extension ThingsToDo {
func doThingTwo() { /* Define code here */}
}
class Person: ThingsToDo {
func doThingOne() {
// Already defined in extension
doThingTwo()
// Rest of code
}
}
拡張機能により、通常のプロトコルの関数が定義されていない場合でもコンパイル時エラーが発生する一方で、関数のデフォルト値を使用できます。