【问题标题】:swift abstract class with shared method [duplicate]具有共享方法的快速抽象类[重复]
【发布时间】:2014-12-24 12:45:28
【问题描述】:

Swift 中没有抽象类。

人们有替代方法来拥有类似的机制。但他们没有回答我的问题。如何构建具有相同功能和不同功能的类族?

Abstract classes in Swift Language 建议我们使用协议而不是抽象基类。但是协议不是我们可以编写函数体的地方,因此对于每个子类中的相同函数,我们必须编写与子类编号相同的函数体。

我想要的是这样的:

protocol Animal : class {
    func run()
    var legs : [Leg] { get }

    // this method is invalid in swift protocol
    // as protocol methods must have no bodies.
    // Instead, the same method will be repeated
    // in every subclasses

    func legCount() -> Int {
       return self.legs.count
    }
}

class Dog : Animal {
    func run() {}
    var legs : [Leg]
}

class Bird : Animal {
    func run() {}
    var legs : [Leg]
}

【问题讨论】:

    标签: design-patterns swift abstract-class virtual-functions


    【解决方案1】:

    这是我可以做到的一种方法:

    1. 声明protocol AnimalType。在其中,定义动物是什么以及它可以做什么,而不是它如何做任何事情。此命名约定在 Swift 标准库中使用:CollectionTypeSequenceTypeIntegerTypeBooleanType 等。
    2. 声明一个class Animal,它定义了所有动物如何做它们共同的事情;对于其他所有内容,只需制作占位符函数或属性(这是您的“抽象”类)。如果您有一个对抽象类调用没有意义的函数,请在其主体中调用 fatalError()
    3. 创建您的特定 class Dogclass Bird 等和 override 函数和/或根据需要添加新函数。

    类似这样的:

    struct Leg { } // Just so it'll run in a Playground
    
    protocol AnimalType: class {
        func run()
        var legs : [Leg] { get }
        func legCount() -> Int
    }
    
    class Animal: AnimalType {
        func run() {
            fatalError("run() can not be called on the Animal class")
        }
    
        var _legs: [Leg]! = nil
        var legs: [Leg] { get { return _legs } }
    
        func legCount() -> Int {
            return legs.count
        }
    }
    
    class Dog: Animal {
        override func run() {
            println("Running Dog!")
        }
    
        override init() {
            super.init()
            _legs = [Leg](count: 4, repeatedValue: Leg())
        }
    }
    
    class Bird : Animal {
        override func run() {
            println("Running Bird!")
        }
    
        override init() {
            super.init()
            _legs = [Leg](count: 2, repeatedValue: Leg())
        }
    }
    

    然后,如果您需要说动物的 Array,请使用协议声明数组,而不是 Animal 类:

    let animals: Array<AnimalType>
    

    尝试一些东西:

    let dog = Dog()
    println("Dogs have \(dog.legCount()) legs.")
    dog.run()
    
    let bird = Bird()
    println("Birds have \(bird.legCount()) legs.")
    bird.run()
    

    将输出:

    Dogs have 4 legs. 
    Running Dog! 
    Birds have 2 legs. 
    Running Bird!
    

    Array 也有效:

    var animals: Array<AnimalType> = [dog, bird]
    var legs = animals.map { $0.legCount() }
    println(legs)
    

    [4, 2]

    而且,虽然Animal 仍然可以被实例化:

    let a = Animal()
    

    在上面调用run()将是一个致命错误:

    a.run()
    

    致命错误:无法在 Animal 类上调用 run():文件 ,第 18 行

    【讨论】:

    • 拥有AnimalType 协议有什么好处?
    • IE,你可以使用let animals : [Animal] = …,我认为你不会因此而失去任何东西。
    • @AaronBrager true,[Animal] 可以正常工作。一般来说,我会说它允许实现相同协议的不同基类。不过,在这种情况下,拥有它可能没有多大意义。
    • class GreatCrystallineEntity: AnimalType { func legCount() -&gt; Int { fatalError("Crystalline Entities don't have legs") } }
    • @AaronBrager 不错 :)
    猜你喜欢
    • 2016-03-19
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    • 2020-02-24
    • 2011-02-09
    • 2018-05-12
    • 2016-06-20
    • 1970-01-01
    相关资源
    最近更新 更多