在 Swift 中是否有一个标准的方法来创建一个“纯虚函数”,即。一个 必须的被每个子类覆盖,如果没有,会导致编译时错误?
对抽象类/虚函数没有任何支持,但是在大多数情况下,您可以使用协议:
protocol SomeProtocol { func someMethod() } class SomeClass: SomeProtocol { func someMethod() {} }
If SomeClass doesn't implement someMethod, you'll get this compile time error:
error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
你有两个选择:
将超类定义为协议而不是类
Pro : 编译时检查每个“子类”(不是实际的子类)是否实现了所需的方法
反对 : “超类”(protocol)不能实现方法或属性
例如:
class SuperClass { func someFunc() { fatalError("Must Override") } } class Subclass : SuperClass { override func someFunc() { } }
Pro : 可以在超类中实现方法和属性
Con : 没有编译时检查
另一个解决方法,如果你没有太多的“虚”方法,是让子类把“实现”作为函数对象传递给基类构造函数:
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 开发的新手,我不能完全确定这是什么时候实现的,但是一个兼顾两者的方法是实现一个协议的扩展:
protocol ThingsToDo { func doThingOne() } extension ThingsToDo { func doThingTwo() { /* Define code here */} } class Person: ThingsToDo { func doThingOne() { // Already defined in extension doThingTwo() // Rest of code } }
扩展允许您拥有函数的默认值,而常规协议中的函数如果没有定义,仍然会提供编译时错误
下面允许从类继承,也允许检查协议的编译时间:)
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() { ... } }
您可以使用协议与断言,正如在 drewag的答案 给你中所建议的那样。 但是,协议的例子不见了,我在这里说明,
drewag
现在每个子类都需要实现在编译时检查的协议。如果 Some Class 没有实现 some Method,那么会得到这个编译时错误:
错误: 输入‘ Some Class’不符合协议‘ Some Protocol’
注意: 这只适用于实现协议的最顶层类。任何子类都可以轻松地忽略协议需求。作为 评论由 memmons
memmons
但是,断言仅在运行时有效。
可以通过将函数传递给初始值设定项来实现。
比如说
open class SuperClass { private let abstractFunction: () -> Void public init(abstractFunction: @escaping () -> Void) { self.abstractFunction = abstractFunction } public func foo() { // ... abstractFunction() } } public class SubClass: SuperClass { public init() { super.init( abstractFunction: { print("my implementation") } ) } }
您可以通过传递 self 作为参数来扩展它:
open class SuperClass { private let abstractFunction: (SuperClass) -> Void public init(abstractFunction: @escaping (SuperClass) -> Void) { self.abstractFunction = abstractFunction } public func foo() { // ... abstractFunction(self) } } public class SubClass: SuperClass { public init() { super.init( abstractFunction: { (_self: SuperClass) in let _self: SubClass = _self as! SubClass print("my implementation") } ) } }
正方 :
Con:
required init
这是我经常做的,导致编译时错误:
class SuperClass {} protocol SuperClassProtocol { func someFunc() } typealias SuperClassType = SuperClass & SuperClassProtocol class Subclass: SuperClassType { func someFunc() { // ... } }