Previous discussion (c. 2015): Making protocol conformance inheritance controllable
Sometimes it makes sense for a class to conform to a protocol, but *not* for its subclasses. An example is the ExpressibleBy…Literal
protocols. It is entirely reasonable for a superclass to have one stored property, and thus be expressible by a literal, whereas a subclass adds more properties and thus cannot be expressed by a literal.
Here is what I want to write:
class A : ExpressibleByIntegerLiteral {
var n: Int
init(n: Int) { self.n = n }
convenience init(integerLiteral value: Int) {
self.init(n: value)
}
}
class B : A {
var s: String
init(n: Int, s: String) {
self.s = s
super.init(n: n)
}
}
However that doesn’t work. There are multiple errors:
• The protocol requirement init(integerLiteral:)
must be required
since A
is not final
.
• Therefore, B
must supply its own implementation of init(integerLiteral:)
.
But B
*shouldn’t* provide that initializer, because it is *not* supposed to be expressible by an integer literal!
• • •
It seems to me that when a protocol’s requirements are all initializers (and/or static
), it ought to be possible to conform a class to that protocol without requiring that its subclasses also conform.
In the previous thread, @Joe_Groff pointed out that it is also possible for conformance to a protocol with instance-member requirements to be non-inherited, since “instances can implicitly upconvert to their conforming base class”, but I am not certain we want to go that far.
A related issue, also mentioned by @Joe_Groff, is that currently “methods often must return dynamic Self
when they'd really prefer to return the base class”.
• • •
Are non-inherited conformances something you would find useful?
Should they be possible for all protocols, or only those with all requirements static
/ init
?
Does it make sense to mark the non-inheritedness on the protocol definition, or on the conforming class?
How important is the dynamic-Self
issue to address?
Any other ideas on the matter?