web-dev-qa-db-ja.com

Swift-サブクラスでオーバーライドする必要があるクラスメソッド

Swiftで「純粋な仮想関数」を作成する標準的な方法はありますか。 mustがすべてのサブクラスによってオーバーライドされ、そうでない場合、コンパイル時エラーが発生するもの

81
JuJoDi

次の2つのオプションがあります。

1.プロトコルを使用する

スーパークラスをクラスではなくプロトコルとして定義する

Pro:各「サブクラス」(実際のサブクラスではない)が必要なメソッドを実装しているかどうかのコンパイル時チェック

Con:「スーパークラス」(プロトコル)はメソッドまたはプロパティを実装できません

2.メソッドのスーパーバージョンでアサートする

例:

class SuperClass {
    func someFunc() {
        fatalError("Must Override")
    }
}

class Subclass : SuperClass {
    override func someFunc() {
    }
}

Pro:スーパークラスでメソッドとプロパティを実装できます

Con:コンパイル時チェックなし

128
drewag

抽象クラス/仮想関数のサポートはありませんが、ほとんどの場合、おそらくプロトコルを使用できます。

protocol SomeProtocol {
    func someMethod()
}

class SomeClass: SomeProtocol {
    func someMethod() {}
}

SomeClassがsomeMethodを実装していない場合、次のコンパイル時エラーが発生します。

error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
34
Connor

以下は、クラスを継承し、プロトコルのコンパイル時チェックを許可します:)

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() { ... }

}
25
JMiguel

「仮想」メソッドがあまりない場合の別の回避策は、サブクラスに「実装」を関数オブジェクトとして基本クラスコンストラクターに渡すことです。

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)
    }
}
13
David Moles

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
    }
}

この拡張機能により、通常のプロトコルの関数は定義されていない場合でもコンパイル時エラーが発生しますが、関数のデフォルト値を持つことができます

0
Jordan