在Swift中,是否有一种标准的方法来创建“纯虚函数”,即每个子类必须重写并且如果没有重写则会导致编译时错误的函数?
在Swift中,是否有一种标准的方法来创建“纯虚函数”,即每个子类必须重写并且如果没有重写则会导致编译时错误的函数?
你有两个选择:
将超类定义为协议而不是类
优点: 在编译时检查每个“子类”(实际上不是子类)是否实现了所需的方法
缺点: “超类”(协议)无法实现方法或属性
例如:
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
优点: 可以在超类中实现方法和属性
缺点: 没有编译时检查
fatalError
不提供编译时检查,但很好的是编译器至少足够聪明,在执行路径调用 fatalError
时不需要你提供方法的返回值。 - bugloafsuper.someFunc()
,尽管你已经覆盖了它,你仍然会得到错误。你知道你不应该调用它,但其他人可能不知道并且只是遵循标准惯例。 - Jakub Truhlář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)
}
}
这是我通常做的,会导致编译时错误:
class SuperClass {}
protocol SuperClassProtocol {
func someFunc()
}
typealias SuperClassType = SuperClass & SuperClassProtocol
class Subclass: SuperClassType {
func someFunc() {
// ...
}
}
protocol SomeProtocol {
func someMethod()
}
class SomeClass: SomeProtocol {
func someMethod() {}
}
注意:这只适用于实现协议的最上层类。任何子类都可以轻松地忽略协议要求。- 由memmons评论。error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
你可以通过将函数传递到初始化器中来实现它。
例如
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")
}
)
}
}
优点:
缺点:
required init
的类作为一个新手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
实现(与Java中的interface
相比)。如果您需要像抽象方法一样使用它们,请查看此问题/答案:http://stackoverflow.com/a/39038828/2435872 - jboi