If a Swift generic type constraint is a protocol name, I can require that two types, constrained to that protocol, be the same type. For example:
protocol Flier {}
struct Bird : Flier {}
struct Insect: Flier {}
func flockTwoTogether<T:Flier>(f1:T, f2:T) {}
The function flockTwoTogether
can be called with a Bird and a Bird or with an Insect and an Insect, but not with a Bird and an Insect. That is the limitation I want. So far, so good.
However, if I try the same thing with a class name, it doesn't work:
class Dog {}
class NoisyDog : Dog {}
class WellBehavedDog: Dog {}
func walkTwoTogether<T:Dog>(d1:T, d2:T) {}
The problem is that I can call walkTwoTogether
with a WellBehavedDog and a NoisyDog. This is what I want to prevent.
There are really two questions here:
Is there a way to say that walkTwoTogether
can't be called with a WellBehavedDog and a NoisyDog?
Is this a bug? I ask because if I can't use a generic to say this, it is hard to see why it is useful for a generic constraint to be a class name at all, since we could get the same result just with a normal function.
Not an answer, per se, but some more data perhaps... The problem is when you call:
walkTwoTogether(NoisyDog(), WellBehavedDog())
Swift can just treat both instances as if they're instances of Dog
(aka, upcast) — we need that so we can call methods meant for class A
with subclasses of A
. (I know you know this.)
Swift doesn't upcast to protocols, so the only way to do it is to specify a protocol for the subclasses that the superclass doesn't conform to:
protocol Walkable {}
extension NoisyDog : Walkable {}
extension WellBehavedDog: Walkable {}
func walkTwoTogether<T: Dog where T: Walkable>(d1:T, d2:T) { }
walkTwoTogether(NoisyDog(), WellBehavedDog())
// error: type 'Dog' does not conform to protocol 'Walkable'
The error message explicitly shows what is going on — the only way to call this version of walkToTogether
is to upcast the subclass instances to Dog
, but Dog
doesn't conform to Walkable
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With