Swift语言中的抽象类

有没有办法在Swift语言创build一个抽象类,或者这是一个像Objective-C的限制? 我想创build一个类似于Java定义为抽象类的抽象类。

Swift中没有抽象类(就像Objective-C一样)。 你最好的select是使用一个协议 ,就像一个Java接口。

使用Swift 2.0,您可以使用协议扩展添加方法实现和计算属性实现。 你唯一的限制是你不能提供成员variables或常量也没有dynamic分派

这种技术的一个例子是:

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协议的每个类或结构都必须再次声明annualSalary属性。

最重要的是,请注意, 没有dynamic调度 。 当存储为SoftwareEngineer的实例上调用logSalary ,将调用该方法的重写版本。 当实例调用logSalary后,调用原始实现(即使实例实际上是Software Engineer它也不会dynamic分派到被覆盖的版本。

有关更多信息,请查看有关该function的伟大WWDCvideo: 使用Swift中的值types构build更好的应用程序

请注意,这个答案是针对Swift 2.0及以上

您可以通过协议和协议扩展实现相同的行为。

首先,编写一个协议,充当所有必须在所有符合它的types中实现的方法的接口。

 protocol Drivable { var speed: Float { get set } } 

然后,您可以将默认行为添加到符合它的所有types

 extension Drivable { func accelerate(by: Float) { speed += by } } 

现在可以通过实施Drivable来创build新的types。

 struct Car: Drivable { var speed: Float = 0.0 init() {} } let c = Car() c.accelerate(10) 

所以基本上你会得到:

  1. 编译时间检查,确保所有Drivable实现speed
  2. 您可以实施符合Drivableaccelerate )的所有types的默认行为
  3. Drivable保证不被实例化,因为它只是一个协议

这个模型实际上performance得更像特征,意味着你可以遵循多个协议,并采取其中任何一个的默认实现,而对于抽象的超类,你仅限于一个简单的类层次结构。

我认为这是最接近Java的abstract或C#的abstract

 class AbstractClass { private init() { } } 

请注意,为了使private修饰符正常工作,您必须在单独的Swift文件中定义此类。

编辑:仍然,这个代码不允许声明一个抽象的方法,从而强制其实施。

在我挣扎了好几个星期之后,我终于意识到如何将Java / PHP抽象类翻译成Swift:

 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()); } } 

不过,我认为苹果没有实现抽象类,因为它通常使用委托+协议模式。 例如,上面的相同的模式会更好地完成这样的事情:

 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等。

有一种使用协议来模拟抽象类的方法。 这是一个例子:

 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 } } 

最简单的方法是在协议扩展中使用对fatalError("Not Implemented")的抽象方法(而不是variables)的调用。

 protocol MyInterface { func myMethod() -> String } extension MyInterface { func myMethod() -> String { fatalError("Not Implemented") } } class MyConcreteClass: MyInterface { func myMethod() -> String { return "The output" } } MyConcreteClass().myMethod() 

如何实现抽象类的另一种方法是阻止初始化器。 我这样做了:

 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") } } } 

我试图做一个Weather抽象类,但是使用协议并不理想,因为我不得不一遍又一遍地写同样的init方法。 扩展协议和写一个init方法有问题,特别是因为我使用符合NSCoding NSObject

所以我想出了NSCoding一致性:

 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... } 

至于init

 fileprivate init(param: Any...) { // Initialize }