简体   繁体   中英

Swift - Why is protocol still treated as generic even though where clause has specialized the associated type?

I have a generic protocol:

protocol GenericProtocol {
  associatedtype GenericParameter
}

I'm not able to use it like this:

var someValue: GenericProtocol?

I get the error message we all know well:

Protocol 'GenericProtocol' can only be used as a generic constraint because it has Self or associated type requirements

Having run into this error many times and having spent a long time pondering the conceptual reason for this error, I think I have grasped it at least somewhat. What I don't understand, is why I can't create a protocol which inherits from and specializes my generic protocol such that it can be used in type signatures. Here is the inheriting protocol:

protocol ConcreteProtocol: GenericProtocol where GenericParameter == Bool { }

But even this I can't use in a type signature:

var someValue: ConcreteProtocol?

Protocol 'ConcreteProtocol' can only be used as a generic constraint because it has Self or associated type requirements

Am I misunderstanding the meaning of a where clause? What is the conceptual reason that even constrained sub-protocols must be treated as generic? I am sure that this is not a bug but rather a purposeful fact of the language which is known to the Swift community. Can anyone explain this to me?

Also if anyone could provide a way in which I can to achieve what I want that would be much appreciated, though I'm not sure it's possible.

var someValue: GenericProtocol?

Why this doesn't work is quite obvious if you think of trying

var someValue: Class = Class1()
someValue            = Class2()

The point is that you have a protocol which is for every type you assign there different, has different method types for example, which makes someValue unusable.

protocol ConcreteProtocol: GenericProtocol where GenericParameter == Bool { }
var someValue: ConcreteProtocol?

does likely not work because classes may want to override the associatedtype and so could not be assigned to someValue . So implementing this in the language would probably deny classes to override, since ConcreteProtcol could use GenericParameter == Bool in one of its extensions already.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM