kev*_*kev 136 inheritance abstract-class subclass swift
有没有办法在Swift语言中创建一个抽象类,或者这是一个像Objective-C一样的限制?我想创建一个类似于Java定义为抽象类的抽象类.
dre*_*wag 168
Swift中没有抽象类(就像Objective-C一样).你最好的选择是使用一个类似Java接口的协议.
使用Swift 2.0,您可以使用协议扩展添加方法实现和计算属性实现.您唯一的限制是您不能提供成员变量或常量,并且没有动态分派.
这种技术的一个例子是:
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
Run Code Online (Sandbox Code Playgroud)
请注意,即使对于结构体,这也提供了类似于"抽象类"的功能,但类也可以实现相同的协议.
另请注意,实现Employee协议的每个类或结构都必须再次声明annualSalary属性.
最重要的是,请注意没有动态调度.当logSalary在存储为实例的实例上SoftwareEngineer调用时,它会调用该方法的重写版本.当logSalary被调用的情况下,已强制转换为后Employee,它会调用原始的实现(它不没有动态分派到重写版本,即使该实例实际上是一个Software Engineer.
有关更多信息,请查看有关该功能的伟大WWDC视频:在Swift中使用值类型构建更好的应用程序
NSA*_*ict 47
请注意,此答案针对的是Swift 2.0及更高版本
您可以使用协议和协议扩展来实现相同的行为.
首先,编写一个协议,作为所有必须在符合它的所有类型中实现的方法的接口.
protocol Drivable {
var speed: Float { get set }
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以将默认行为添加到符合它的所有类型
extension Drivable {
func accelerate(by: Float) {
speed += by
}
}
Run Code Online (Sandbox Code Playgroud)
您现在可以通过实现创建新类型Drivable.
struct Car: Drivable {
var speed: Float = 0.0
init() {}
}
let c = Car()
c.accelerate(10)
Run Code Online (Sandbox Code Playgroud)
所以基本上你得到:
Drivable的实现speedDrivable(accelerate)的所有类型实现默认行为Drivable 保证不会被实例化,因为它只是一个协议这个模型实际上更像是traits,这意味着你可以符合多个协议并采用其中任何一个的默认实现,而对于一个抽象的超类,你只能局限于一个简单的类层次结构.
Tee*_*jay 14
我认为这是最接近Java abstract或C#的abstract:
class AbstractClass {
private init() {
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,为了使private修饰符起作用,必须在单独的Swift文件中定义此类.
编辑:仍然,此代码不允许声明一个抽象方法,从而强制其实现.
Jos*_*ock 10
经过几周的努力,我终于意识到如何将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());
}
}
Run Code Online (Sandbox Code Playgroud)
但是我认为Apple没有实现抽象类,因为它通常使用委托+协议模式.例如,上面相同的模式最好这样做:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
我需要这种模式,因为我想在UITableViewController中使用一些方法,例如viewWillAppear等.这有用吗?
小智 9
最简单的方法是使用fatalError("Not Implemented")对协议扩展的抽象方法(非变量)的调用.
protocol MyInterface {
func myMethod() -> String
}
extension MyInterface {
func myMethod() -> String {
fatalError("Not Implemented")
}
}
class MyConcreteClass: MyInterface {
func myMethod() -> String {
return "The output"
}
}
MyConcreteClass().myMethod()
Run Code Online (Sandbox Code Playgroud)
有一种方法可以使用Protocols模拟抽象类.这是一个例子:
protocol MyProtocol {
func doIt()
}
class BaseClass {
weak var myDelegate: MyProtocol?
init() {
...
}
func myFunc() {
...
self.myDelegate?.doIt()
...
}
}
class ChildClass: BaseClass, MyProtocol {
override init(){
super.init()
self.myDelegate = self
}
func doIt() {
// Custom implementation
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
77275 次 |
| 最近记录: |