[swift-evolution] Making protocol conformance inheritance controllable

Joe Groff jgroff at apple.com
Fri Dec 11 14:21:55 CST 2015


> On Dec 10, 2015, at 8:04 PM, Michel Fortin <michel.fortin at michelf.ca> wrote:
> 
> Le 10 déc. 2015 à 21:04, Joe Groff via swift-evolution <swift-evolution at swift.org> a écrit :
> 
>> And if a class hierarchy really wants to impose a conformance on all possible subclasses, as happens today, we could let you opt in to that:
>> 
>> class E: required Fungible {
>>  // init() must be required of all subclasses
>>  required init() { }
>> 
>>  // funged() must return a covariant object
>>  class func funged() -> Self { return Self() }
>> }
> 
> I think the concept makes sense. But you're changing the default behaviour here. Is this because you expect protocols should not be inherited most of the time? That most protocols in Cocoa shouldn't be inherited? That goes against "obvious way things should be".

It's a good question which behavior ought to be default. The good news is that the distinction is only observable for protocols with covariant requirements—initializers, methods returning Self, or properties of type Self. A more conservative change might be:

- preserve the current inheritance behavior for protocols without covariant requirements;
- when a class conforms to a protocol with covariant requirements, it must specify whether the conformance is `static` or  `required`, so that neither behavior is default.

> Also, shouldn't this be allowed too?
> 
> 	class F: C, required override Fungible {
> 		required init() { }
> 		class func funged() -> Self { return Self() }
> 	}

'required override' would be unnecessary in any case. The base class requiring the conformance implies that every derived class inherits it already, and derived classes can already influence the conformance by normal method overriding.

-Joe

> Personally, I'd tend to make 'required' the default mode, and use "static Fungible" for the odd one that does not apply to subtypes. And I'd get rid of override before the protocol name, just use "static Fungible" again in the subclass:
> 
> 	class C: static Fungible {
> 		init() {}
> 		class func funged() -> C { return C() }
> 	}
> 	class D: C, static Fungible {
> 		init() {}
> 		override class func funged() -> D { return D() }
> 	}
> 	class E: Fungible {
> 		required init() {}
> 		class func funged() -> Self { return Self() }
> 	}
> 	class F: C, Fungible {
> 		required init() {}
> 		override class func funged() -> Self { return Self() }
> 	}
> 
> But in the end the syntax depends on what default behaviour is desired.
> 
> -- 
> Michel Fortin
> michel.fortin at michelf.ca
> https://michelf.ca
> 



More information about the swift-evolution mailing list