首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >协变覆盖?

协变覆盖?
EN

Stack Overflow用户
提问于 2016-09-05 14:21:06
回答 4查看 1.4K关注 0票数 3

在Swift中有支持协变量返回类型的方法吗?

例如,我想支持以下场景:

代码语言:javascript
复制
class Animal {}
class Dog : Animal{}
class Cat : Animal {}

class AnimalResidency{
    func getAllAnimals() -> Array<Animal> {
        return []
    }
}
class Cattery : AnimalResidency{
    override func getAllAnimals() -> Array<Cat> {
        return [Cat(), Cat()]
    }
}
class DogKennel : AnimalResidency {
    override func getAllAnimals() -> Array<Dog> {
        return [Dog(), Dog(), Dog(), Dog()]
    }
}

重写的func会产生编译器错误,因为重写签名与基本定义不完全匹配,尽管可以清楚地看到重写返回的内容仍然符合基本定义的约定。

我是否有办法达到上述目的?我甚至很想知道Swift 3的答案。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-09-05 16:02:21

我不确定是否有必要按照您的要求做--即重写getAllAnimals而不是重载它。使用泛型是一种可能的解决方案--看看这是否适用于您:

代码语言:javascript
复制
class Animal { var description: String { return "Animal" } }
class Dog : Animal { override var description: String { return "Dog" } }        
class Cat : Animal { override var description: String { return "Cat" } }

class AnimalResidency<T: Animal>{
    func getAllAnimals<T>() -> Array<T> {
        return []
    }
}

class Cattery : AnimalResidency<Cat> {
    func getAllAnimals() -> Array<Cat> {
        return [Cat()]
    }
}

class DogKennel : AnimalResidency<Dog> {
    func getAllAnimals() -> Array<Dog> {
        return [Dog(), Dog()]
    }
}

let c = Cattery()
c.getAllAnimals().first?.description // "Cat"
let d = DogKennel()
d.getAllAnimals().first?.description // "Dog"

然而,我自己的想法并不是使用两个平行的类层次结构,而是尝试这样的东西.

代码语言:javascript
复制
class Animal {
    var description: String { return "Animal" }
    required init() {}
}
class Dog : Animal {
    override var description: String { return "Dog" }
}
class Cat : Animal {
    override var description: String { return "Cat" }
}

extension Animal {
    class func home() -> [Animal] {
        return [self.init()]
    }
}

let c = Cat.home().first?.description // "Cat"
let d = Dog.home().first?.description // "Dog"
票数 4
EN

Stack Overflow用户

发布于 2016-09-05 14:45:52

迅速使用面向协议的范例。所以根据你的要求。在您的情况下,最好使用协议和PATs。

什么是拍。

代码语言:javascript
复制
protocol BaseProtocol {
    //PAT's
    typealias ReturnType: BaseType
    func someFunction() -> ReturnType
}

class SomeClass : BaseProtocol {
    func someFunction() -> BaseType {  }
}
票数 1
EN

Stack Overflow用户

发布于 2016-09-05 14:40:54

正如您已经注意到的,签名必须完全相同。

但是您可以使用[Base]作为Derived-class中的返回类型。

代码语言:javascript
复制
class Base {
    var a = "A" //just a property to check if you can access properties of this class

    var test: [Base] {
        return [self]
    }

    func test2() -> [Base] {
        return [self]
    }
}

class Derived: Base {
    var b = "B" //just a property to check if you can access properties of this class

    override var test: [Base] {
        return [self]
    }

    override func test2() -> [Base] {
        return [self]
    }
}

您可以使用test2()test (计算属性)。

在访问存储在数组中的对象的属性之前,必须将其转换为Derived.

代码语言:javascript
复制
let d = Derived()
let dArray = d.test2()

print((dArray[0] as! Derived).b) //Prints "B"
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39332630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档