Inheritance Swift语言中的抽象类

Inheritance Swift语言中的抽象类,inheritance,abstract-class,subclass,swift,Inheritance,Abstract Class,Subclass,Swift,有没有办法用Swift语言创建一个抽象类,或者这和Objective-C一样是一个限制?我想创建一个与Java定义的抽象类相当的抽象类。Swift中没有抽象类(就像Objective-C一样)。您最好的选择是使用类似于Java接口的 使用Swift 2.0,您可以使用协议扩展添加方法实现和计算属性实现。您唯一的限制是不能提供成员变量或常量,并且没有动态分派 这种技术的一个例子是: protocol Employee { var annualSalary: Int {get} } ext

有没有办法用Swift语言创建一个抽象类,或者这和Objective-C一样是一个限制?我想创建一个与Java定义的抽象类相当的抽象类。

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
注意,这甚至为结构提供了类似“抽象类”的特性,但类也可以实现相同的协议

还要注意,实现Employee协议的每个类或结构都必须再次声明annualSalary属性

最重要的是,请注意,没有动态分派。当对存储为
softwareenger
的实例调用
logSalary
时,它将调用该方法的重写版本。在实例被转换为
员工
后,当对该实例调用
logSalary
时,它调用原始实现(即使该实例实际上是
软件工程师
,它也不会动态调度到覆盖的版本)


有关更多信息,请查看有关该功能的精彩WWDC视频:

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
注意,这甚至为结构提供了类似“抽象类”的特性,但类也可以实现相同的协议

还要注意,实现Employee协议的每个类或结构都必须再次声明annualSalary属性

最重要的是,请注意,没有动态分派。当对存储为
软件工程师的实例调用
logSalary
时,它将调用方法的重写版本。当将实例转换为
员工
后对该实例调用
logSalary
时,它将调用原始实现(即使实例实际上是
软件工程师
,它也不会动态地分派到覆盖的版本


有关更多信息,请查看有关该功能的精彩WWDC视频:

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

class AbstractClass {

    private init() {

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


EDIT:不过,这段代码不允许声明抽象方法,从而强制实现它。

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

class AbstractClass {

    private init() {

    }
}
请注意,为了使
专用
修饰符正常工作,必须在单独的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());
    }
}
但是,我认为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());
        }
    }

我需要这种模式,因为我想在UITableViewController中通用一些方法,如viewWillAppear等。这有帮助吗?

经过几周的努力,我终于意识到如何将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());
    }
}
但是,我认为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());
        }
    }
我需要这种模式,因为我想在UITableViewController中通用一些方法,如ViewWillExample等。这有帮助吗?

注意,这个答案是针对Swift 2.0及以上版本的

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

首先,编写一个协议,作为所有方法的接口,这些方法必须在符合它的所有类型中实现

protocol Drivable {
    var speed: Float { get set }
}
然后,您可以将默认行为添加到符合它的所有类型中

extension Drivable {
    func accelerate(by: Float) {
        speed += by
    }
}
现在可以通过实现
Drivable
来创建新类型

struct Car: Drivable {
    var speed: Float = 0.0
    init() {}
}

let c = Car()
c.accelerate(10)
所以基本上你会得到:

  • 编译时检查确保所有
    Drivable
    s实现
    speed
  • 您可以为符合
    Drivable
    accelerate
    )的所有类型实现默认行为
  • Drivable
    保证不会被实例化,因为它只是一个协议
  • 这个模型实际上表现得更像traits,这意味着您可以遵守多个协议并接受其中任何一个的默认实现,而对于抽象超类,您仅限于一个简单的类层次结构。

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

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

    首先,编写一个协议,作为所有方法的接口,这些方法必须在符合它的所有类型中实现

    protocol Drivable {
        var speed: Float { get set }
    }
    
    然后,您可以将默认行为添加到符合它的所有类型中

    extension Drivable {
        func accelerate(by: Float) {
            speed += by
        }
    }
    
    现在可以通过实现
    Drivable
    来创建新类型

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