是否有标准的方法来制作一个纯粹的虚拟功能"在斯威夫特,即。一个必须被每个子类覆盖,如果不是,会导致编译时错误?
答案 0 :(得分:126)
您有两种选择:
将超类定义为协议而不是类
Pro :编译时间检查每个“子类”(不是实际的子类)是否实现了所需的方法
Con :“超类”(协议)无法实现方法或属性
示例:
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
Pro :可以在超类中实现方法和属性
Con :无编译时检查
答案 1 :(得分:36)
对抽象类/虚函数没有任何支持,但在大多数情况下你可能会使用协议:
protocol SomeProtocol {
func someMethod()
}
class SomeClass: SomeProtocol {
func someMethod() {}
}
如果SomeClass没有实现someMethod,那么你将得到这个编译时错误:
error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
答案 2 :(得分:21)
以下内容允许从类继承,并允许检查协议的编译时间:)
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() { ... }
}
答案 3 :(得分:14)
另一种解决方法,如果你没有太多"虚拟"方法,是让子类传递"实现"作为函数对象进入基类构造函数:
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)
}
}
答案 4 :(得分:2)
您可以按照drewag
的答案here中的建议使用协议与声明。
但是,缺少该协议的示例。我在这里报道,
protocol SomeProtocol {
func someMethod()
}
class SomeClass: SomeProtocol {
func someMethod() {}
}
现在,需要每个子类来实现在编译时检查的协议。如果SomeClass没有实现someMethod,则会出现此编译时错误:
错误:类型“ SomeClass”不符合协议“ SomeProtocol”
注意:这仅适用于实现协议的最高级类。任何子类都可以巧妙地忽略协议要求。 –由memmons
的{{3}}
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
但是,断言仅在运行时有效。
答案 5 :(得分:1)
这是我通常做的,导致编译时错误:
class SuperClass {}
protocol SuperClassProtocol {
func someFunc()
}
typealias SuperClassType = SuperClass & SuperClassProtocol
class Subclass: SuperClassType {
func someFunc() {
// ...
}
}
答案 6 :(得分:0)
您可以通过将函数传递给初始化程序来实现。
例如
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
答案 7 :(得分:0)
我也想要这个编译时检查。我没有彻底研究提出的解决方案,但我认为协议解决方案行不通,因为继承的方法满足协议要求。
答案 8 :(得分:-1)
作为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
}
}
使用扩展名可以使函数具有默认值,而常规协议中的函数仍会提供编译时错误(如果未定义)