Swift - 类方法,必须由子类重写

JuJ*_*oDi 82 abstract swift swift-protocols

是否有一种在Swift中制作"纯虚函数"的标准方法,即.一个必须被每个子类覆盖的,如果不是,会导致编译时错误?

dre*_*wag 133

您有两种选择:

1.使用协议

将超类定义为协议而不是类

Pro:编译时间检查每个"子类"(不是实际的子类)是否实现了所需的方法

Con:"超类"(协议)无法实现方法或属性

2.在方法的超级版本中断言

例:

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

class Subclass : SuperClass {
    override func someFunc() {
    }
}
Run Code Online (Sandbox Code Playgroud)

Pro:可以在超类中实现方法和属性

Con:没有编译时检查

  • 协议无法实现方法,但您可以通过扩展方法提供它们. (4认同)
  • 虽然`fatalError`不提供编译时检查,但编译器至少足够聪明,当执行路径调用`fatalError`时不要求你为方法提供返回值. (4认同)
  • @jewirth你仍然不会对子类进行编译时检查 (3认同)
  • 从Swift 2.0开始,现在也有协议扩展:) [Apple Reference](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/UID/TP40014097-CH25-ID521). (2认同)
  • *情况2:*请注意,如果您从覆盖的方法中调用`super.someFunc()`,尽管您覆盖了该错误,但仍会收到错误。您知道您不应该称呼它,但是其他人不必知道,只需遵循标准做法即可。 (2认同)

Con*_*nor 34

对抽象类/虚函数没有任何支持,但在大多数情况下你可能会使用协议:

protocol SomeProtocol {
    func someMethod()
}

class SomeClass: SomeProtocol {
    func someMethod() {}
}
Run Code Online (Sandbox Code Playgroud)

如果SomeClass没有实现someMethod,你将得到这个编译时错误:

error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这仅适用于实现协议的最顶级类.任何子类都可以轻率地忽略协议要求. (28认同)
  • 此外,不支持在协议上使用泛型 =( (3认同)

JMi*_*uel 31

以下允许从类继承并且还要对协议的编译时间进行检查:)

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

}
Run Code Online (Sandbox Code Playgroud)

  • 不错,typealias 来救援:) (3认同)

Dav*_*les 13

另一种解决方法是,如果没有太多"虚拟"方法,则让子类将"实现"作为函数对象传递给基类构造函数:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)