swift - 子类可以覆盖函数并进行更严格的返回吗?

标签 swift

我正在尝试这种技术:

class Pet {}

class Dog: Pet {}

class House {
    func getPets() -> [Pet] {
        return [Pet]()
    }
}

class DogHouse: House {
    override func getPets() -> [Dog] {
        return [Dog]()
    }
}

DogHouse 类以严格满足 House API 要求的方式覆盖了 House getPets 方法getPets.

但是,Swift 不理解 [Dog][Pet] 并且它会产生错误 Method does not override any method from its superclass.

有什么方法可以让子类实现比其父类(super class)具有更多通用输入或更多限制性输出的 API?

最佳答案

回答官方提出的问题:是的,Swift允许在返回类型中有更多“受限”的返回类型。此属性的正式名称是返回类型协方差。考虑这个例子,它是可编译的 Swift 代码:

class Pet {}

class Dog: Pet {}

class House {
    func getPets() -> Pet {
        return Pet()
    }
}

class DogHouse: House {
    override func getPets() -> Dog {
        return Dog()
    }
}

但是,这里的问题是 Array<Dog>不是比 Array<Pet> 更受限制的类型,反之,Array<Pet> 不是 Array<Dog> 的概括.正式地,Array<Dog>不是 Array<Pet> 的协变.

为了说明原因,请考虑以下示例:

class House<T> {
    var occupants = [T]()

    func addOccupant(_ o: T) {
        occupants.append(o)
    }
}

class Pet {}
class Dog: Pet {}
class Cat: Pet {}

class PetHouseBuilder {
    func buildHouse() -> House<Pet> {
        return House()
    }
}

class DogHouseBuilder: PetHouseBuilder {
    // Suppose this were legal
    override func buildHouse() -> House<Dog> {
        return House()
    }
}

// The concrete return type of the object is `House<Dog>`, but
// `PetHouseBuilder.buildHouse` has a static return type of `House<Pet>`,
// so `petHouse` will have an inferred static type of `House<Pet>`
let petHouse = PetHouseBuilder().buildHouse()

let vulnerableLittle🐱 = Cat()
petHouse.addOccupant(vulnerableLittle🐱)
// Oh boy, now there's a kitten in the dog house ☠️

关于swift - 子类可以覆盖函数并进行更严格的返回吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42615710/

相关文章:

ios - UITableViewCell 阴影

swift - 如何使用 UITableViewCells 制作可 ScrollView

swift - for(增加时间延迟)取决于对象数量

ios - 在 Realm 之间复制对象时需要迁移

ios - 在 Swift 中使用 C API

ios - 其他 swift 标志中 "-D"的含义是什么

ios - 保存和读取图像阵列

swift - 尝试执行 Realm 迁移时获取无效的属性名称

ios - UITableview中Multiple cells的数组结构如何设计?

ios - Swift 编译器错误 : “Cannot invoke ' map' with an argument list of type '((_) -> _)' ”