子类是否可以覆盖函数并进行更严格的返回?

时间:2017-03-06 00:20:32

标签: swift

我正在尝试这种技术:

class Pet {}

class Dog: Pet {}

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

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

DogHouse类以严格符合House getPets的API要求的方式覆盖House getPets方法。

但是,Swift并不认为[Dog] isa [Pet]会产生错误Method does not override any method from its superclass

子类是否有任何方法可以使用比其超类更通用的输入或更严格的输出来实现API?

2 个答案:

答案 0 :(得分:5)

回答官方提出的问题:是的,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 ☠️

答案 1 :(得分:0)

@亚历山大

嗨,也许您知道,为什么您的示例不适用于协议?

protocol IPet {}

protocol IDog: IPet {}

class Pet: IPet {}

class Dog: Pet, IDog {}

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

class DogHouse: House {
    override func getPets() -> IDog //Method does not override any method from its superclass
    { 
        return Dog()
    }
}

谢谢。