Abstract classes in Swift Language
有没有一种方法可以用Swift语言创建抽象类,或者这是一个像Objective-C一样的限制?我想创建一个与Java定义为抽象类的抽象类。
在swift中没有抽象类(就像objective-c)。最好的办法是使用一个协议,它就像一个Java接口。
使用Swift2.0,您可以使用协议扩展添加方法实现和计算属性实现。您唯一的限制是不能提供成员变量或常量,并且没有动态调度。
这种技术的一个例子是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | protocol Employee { var annualSalary: Int {get} } extension Employee { var biweeklySalary: Int { return self.annualSalary / 26 } func logSalary() { print("$\(self.annualSalary) per year or $\(self.biweeklySalary) biweekly") } } struct SoftwareEngineer: Employee { var annualSalary: Int func logSalary() { print("overridden") } } let sarah = SoftwareEngineer(annualSalary: 100000) sarah.logSalary() // prints: overridden (sarah as Employee).logSalary() // prints: $100000 per year or $3846 biweekly |
注意,这甚至为结构提供了类似"抽象类"的特性,但是类也可以实现相同的协议。
还请注意,实现Employee协议的每个类或结构都必须再次声明annualslary属性。
最重要的是,请注意没有动态调度。当对存储为
有关更多信息,请查看有关该功能的精彩WWDC视频:使用swift中的值类型构建更好的应用程序
请注意,此答案针对的是Swift 2.0及以上版本。
您可以通过协议和协议扩展实现相同的行为。
首先,编写一个协议,作为所有必须在所有符合该协议的类型中实现的方法的接口。
1 2 3 | protocol Drivable { var speed: Float { get set } } |
然后,您可以将默认行为添加到所有符合它的类型中。
1 2 3 4 5 | extension Drivable { func accelerate(by: Float) { speed += by } } |
现在,您可以通过实现
1 2 3 4 5 6 7 | struct Car: Drivable { var speed: Float = 0.0 init() {} } let c = Car() c.accelerate(10) |
所以基本上你会得到:
这个模型实际上的行为更像特征,这意味着你可以遵守多个协议并采用其中任何一个协议的默认实现,而对于一个抽象的超类,你只能使用一个简单的类层次结构。
我认为这是最接近Java的EDCOX1的5或C的EDOCX1的5个方面:
1 2 3 4 5 6 | class AbstractClass { private init() { } } |
注意,为了使
编辑:尽管如此,此代码不允许声明抽象方法,从而强制实现它。
最简单的方法是在协议扩展上使用对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | protocol MyInterface { func myMethod() -> String } extension MyInterface { func myMethod() -> String { fatalError("Not Implemented") } } class MyConcreteClass: MyInterface { func myMethod() -> String { return"The output" } } MyConcreteClass().myMethod() |
在我挣扎了几个星期之后,我终于意识到如何将Java/PHP抽象类翻译成SWIFT:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | public class AbstractClass: NSObject { internal override init(){} public func getFoodToEat()->String { if(self._iAmHungry()) { return self._myFavoriteFood(); }else{ return""; } } private func _myFavoriteFood()->String { return"Sandwich"; } internal func _iAmHungry()->Bool { fatalError(__FUNCTION__ +"Must be overridden"); return false; } } public class ConcreteClass: AbstractClass, IConcreteClass { private var _hungry: Bool = false; public override init() { super.init(); } public func starve()->Void { self._hungry = true; } public override func _iAmHungry()->Bool { return self._hungry; } } public protocol IConcreteClass { func _iAmHungry()->Bool; } class ConcreteClassTest: XCTestCase { func testExample() { var concreteClass: ConcreteClass = ConcreteClass(); XCTAssertEqual("", concreteClass.getFoodToEat()); concreteClass.starve(); XCTAssertEqual("Sandwich", concreteClass.getFoodToEat()); } } |
然而,我认为苹果没有实现抽象类,因为它通常使用委托+协议模式。例如,上面的相同模式最好这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | import UIKit public class GoldenSpoonChild { private var delegate: IStomach!; internal init(){} internal func setup(delegate: IStomach) { self.delegate = delegate; } public func getFoodToEat()->String { if(self.delegate.iAmHungry()) { return self._myFavoriteFood(); }else{ return""; } } private func _myFavoriteFood()->String { return"Sandwich"; } } public class Mother: GoldenSpoonChild, IStomach { private var _hungry: Bool = false; public override init() { super.init(); super.setup(self); } public func makeFamilyHungry()->Void { self._hungry = true; } public func iAmHungry()->Bool { return self._hungry; } } protocol IStomach { func iAmHungry()->Bool; } class DelegateTest: XCTestCase { func testGetFood() { var concreteClass: Mother = Mother(); XCTAssertEqual("", concreteClass.getFoodToEat()); concreteClass.makeFamilyHungry(); XCTAssertEqual("Sandwich", concreteClass.getFoodToEat()); } } |
我需要这种模式,因为我想在uiTableViewController中通用一些方法,如ViewWillAppear等。这有帮助吗?
有一种方法可以使用协议模拟抽象类。这是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | protocol MyProtocol { func doIt() } class BaseClass { var myDelegate: MyProtocol! init() { ... } func myFunc() { ... self.myDelegate.doIt() ... } } class ChildClass: BaseClass, MyProtocol { override init(){ super.init() self.myDelegate = self } func doIt() { // Custom implementation } } |
实现抽象类的另一种方法是阻止初始值设定项。我是这样做的:
1 2 3 4 5 6 7 8 9 | class Element:CALayer { // IT'S ABSTRACT CLASS override init(){ super.init() if self.dynamicType === Element.self { fatalError("Element is abstract class, do not try to create instance of this class") } } } |
由于没有动态调度的限制,您可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | import Foundation protocol foo { static var instance: foo? { get } func prt() } extension foo { func prt() { if Thread.callStackSymbols.count > 30 { print("super") } else { Self.instance?.prt() } } } class foo1 : foo { static var instance : foo? = nil init() { foo1.instance = self } func prt() { print("foo1") } } class foo2 : foo { static var instance : foo? = nil init() { foo2.instance = self } func prt() { print("foo2") } } class foo3 : foo { static var instance : foo? = nil init() { foo3.instance = self } } var f1 : foo = foo1() f1.prt() var f2 : foo = foo2() f2.prt() var f3 : foo = foo3() f3.prt() |
将对基类的抽象属性和方法的所有引用移动到协议扩展实现,其中自约束到基类。您将获得对基类的所有方法和属性的访问权。另外,编译器检查派生类协议中抽象方法和属性的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | protocol Commom:class{ var tableView:UITableView {get}; func update(); } class Base{ var total:Int = 0; } extension Common where Self:Base{ func update(){ total += 1; tableView.reloadData(); } } class Derived:Base,Common{ var tableView:UITableView{ return owner.tableView; } } |
我试图创建一个
因此,我为
1 2 3 4 5 6 | required init?(coder aDecoder: NSCoder) { guard type(of: self) != Weather.self else { fatalError("<Weather> This is an abstract class. Use a subclass of `Weather`.") } // Initialize... } |
对于
1 2 3 | fileprivate init(param: Any...) { // Initialize } |