[swift-evolution] Proposal: Universal dynamic dispatch for method calls
Paul Cantrell
cantrell at pobox.com
Tue Dec 8 23:31:04 CST 2015
Gwendal Roué wrote:
> Whatever the direction this proposal is aiming at, please remember that it is desirable for some APIs to let adopting types "override" the default implementation provided by protocols.
I would certainly hope nobody is proposing changing that! Once a method is virtually dispatched, it should be virtual all the way down to the implementing type.
P
> On Dec 8, 2015, at 10:21 PM, Gwendal Roué via swift-evolution <swift-evolution at swift.org> wrote:
>
>> Le 9 déc. 2015 à 00:26, Kevin Ballard via swift-evolution <swift-evolution at swift.org> a écrit :
>>
>>> Keep in mind that what I’m proposing here doesn’t actually change Swift’s runtime behavior at all. Note #2—you’re *required* to make protocol extension members `final` unless they’re listed in the protocol declaration. What I’m proposing is merely a series of compile-time statements used to tell swiftc that, yes, I know this is going to happen.
>
> Whatever the direction this proposal is aiming at, please remember that it is desirable for some APIs to let adopting types "override" the default implementation provided by protocols.
>
> The current static dispatch of protocol extensions allows adopting types to perform such an "override":
>
> protocol Feature { }
> extension Feature {
> func run() {
> // default implementation
> }
> }
> struct S : Feature {
> func run() {
> // "inherited" from Feature:
> (self as Feature).run()
> // extra code
> ...
> }
> }
>
> This is important, because *without* this static dispatch, the protocol P *must* be turned into a *base class* as soon as three conditions are met:
>
> - the implementation inside the run() function is rather complex
> - it is desirable to let adopting types able to alter the default behavior.
> - bloating the API and the documentation with extra global functions or extra methods that work around this limitation of the language is not desirable
>
> // Terse API with a Feature base class:
> class Feature {
> func run() {
> // rather complex implementation
> }
> }
> class C : Feature {
> func run() {
> // Inherited from Feature:
> super.ext()
> // extra code
> ...
> }
> }
>
> // Non-terse API with extra methods and documentation:
> protocol Feature { }
> extension Feature {
> func run() {
> self._run()
> }
> /// Don't call this method directly, but use run() instead.
> /// Adopting types may call this method in their own implementation
> /// of run().
> func _run() {
> // default implementation
> }
> }
> struct S : Feature {
> func run() {
> // "inherited" from Feature:
> self._run()
> // extra code
> ...
> }
> }
>
> You have understood that I'm against those extra methods and documentation, and that I prefer the base class solution, despite protocols being all the rage.
>
> Actually, the use case I'm talking here is not properly addressed by the current state of Swift because of a bug with mutating methods https://bugs.swift.org/browse/SR-142 which has the consequence of forcing APIs to keep on exposing a base class instead of a protocol (see https://github.com/groue/GRDB.swift/issues/12 for a practical problem).
>
> Anyway, please remember that it is desirable for some APIs to let adopting types "override" the default implementation provided by protocols.
>
> Gwendal Roué
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
More information about the swift-evolution
mailing list