Ian Newson Ian Newson - 3 months ago 11
Swift Question

Swift: Covariant overrides?

is there any way of supporting covariant return types in Swift?

For example, I'd like to support the following scenario:

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()]
}
}


The overridden func produces a compiler error because the overrides signature doesn't exactly match the base definition, even though it's clear to see the contents returned by the override would still meet the contract of the base definition.

Is there any way for me to achieve the above? I'd even appreciate an answer for Swift 3.

Answer

I'm not sure exactly why you want to do exactly what you ask - i.e. override getAllAnimals rather than overload it. Using generics is a possible solution - please explain why this wouldn't satisfy you:

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"