Swiftで「純粋な仮想関数」を作成する標準的な方法はありますか。 mustがすべてのサブクラスによってオーバーライドされ、そうでない場合、コンパイル時エラーが発生するもの
次の2つのオプションがあります。
スーパークラスをクラスではなくプロトコルとして定義する
Pro:各「サブクラス」(実際のサブクラスではない)が必要なメソッドを実装しているかどうかのコンパイル時チェック
Con:「スーパークラス」(プロトコル)はメソッドまたはプロパティを実装できません
例:
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
Pro:スーパークラスでメソッドとプロパティを実装できます
Con:コンパイル時チェックなし
抽象クラス/仮想関数のサポートはありませんが、ほとんどの場合、おそらくプロトコルを使用できます。
protocol SomeProtocol {
func someMethod()
}
class SomeClass: SomeProtocol {
func someMethod() {}
}
SomeClassがsomeMethodを実装していない場合、次のコンパイル時エラーが発生します。
error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
以下は、クラスを継承し、プロトコルのコンパイル時チェックを許可します:)
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() { ... }
}
「仮想」メソッドがあまりない場合の別の回避策は、サブクラスに「実装」を関数オブジェクトとして基本クラスコンストラクターに渡すことです。
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)
}
}
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
}
}
この拡張機能により、通常のプロトコルの関数は定義されていない場合でもコンパイル時エラーが発生しますが、関数のデフォルト値を持つことができます