Search code examples
swiftprotocolsswift-protocolsdesign-principlesassociated-types

Is there any non written rule that an associatedtype shouldn't be constrained by a concrete type?


class Human {
    var name : String?
}

class Man : Human {
    var numberOfWallets : Int?
}

class Woman : Human {
    var numberOfPurses : Int?
}

protocol P {
    associatedtype Person : Human
    func printX(of person : Person)
    func printY(of person: Person)
}

Which allows Human to be its typealias:

class C : P {
    typealias Person = Human
    func printX(of person: Human) {
        print(person.numberOfCars)
    }

    func printY(of person: Human) {
        print(person.name)
    }
}

As you can see the Person type is constrained by Human which itself is a concrete type. I'm wondering if this is common. My intuition tells me that it's actually a sign that I shouldn't be use protocols, and rather classes itself are just fine.

or I should just do

protocol P {
    associatedtype Person
    func printX(of person : Person)
    func printY(of person: Person)
}

class C : P {
    func printX(of person: Man) {
        print(person.numberOfCars)
    }

    func printY(of person: Man) {
        print(person.name)
    }
}

Which won't allow a Woman & Man instanced to be simultaneously used against a C instance.

I know it depends on what I want to do. But my question really is: Is constraining an asscoiatedtype with a concrete type ever meaningful?!

Or associatedtypes are just there to be either unconstrained or constrained by a protocol, not a concrete type...


Solution

  • In this line

     associatedtype Person : Human
    

    The constraint is not concrete or not. It works in parallel fashion for both kinds of inheritance.

    • If Human is a protocol, Person must be a concrete type that adopts it.

    • If Human is a class, Person must be a concrete type that descends from it.

    Both are useful and legal, and very similar to one another.