[swift-evolution] Calling a Specific Implementation

John McCall rjmccall at apple.com
Fri Aug 19 15:10:35 CDT 2016


> On Aug 19, 2016, at 12:56 PM, Jonathan Hull <jhull at gbis.com> wrote:
> 
> For my own education, how is does it break the encapsulation in a way which subclassing does not?  I may not have mentioned it, but in my mind, this construct would be limited by the compiler to being called from within a conforming type (in the same way super is).  Given that, 

You did not, in fact, mention that. :)  Like "super", you would still want to restrict this to "self", or at the very least to only objects of your own class type, so that you can't just make a subclass and then apply it to an arbitrary object.

In that case, it's basically just super dispatch, except that you can go to an arbitrary protocol-extension implementation.  (Unless you really want to be able to skip your superclass's implementation, which is encapsulation-breaking again.)

John. 

> it seems to me that the considerations by both the ancestor class and the subclass would be exactly the same as in a super-subclass relationship.  I agree that it wouldn’t be a frequent use case, but I have definitely had times where it would have greatly simplified my class structure if allowed.  I don’t see any reason to limit it (beyond the needs of the type), but I could easily be missing something fairly obvious...
> 
> Thanks,
> Jon
> 
>> On Aug 17, 2016, at 6:57 PM, John McCall <rjmccall at apple.com <mailto:rjmccall at apple.com>> wrote:
>> 
>>> On Aug 17, 2016, at 5:46 PM, Jonathan Hull via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> I believe this affects the ABI (especially the second part), but if not, let me know and we can talk about it in phase 2...
>>> 
>>> There are times where you would like to call a specific implementation of a method.  One of the most common is calling super from a subclass, but you may want to do similar things when overriding a default implementation of a protocol.  I also have definitely had times where I wanted to call the implementation of an ancestor other than super.  It also solves some of the issues that came up during the non-subclassable by default discussion, because it allows you to statically dispatch to a known implementation in cases where you need that assurance, but don’t want to mark a method final.  (essentially it gives you the benefits of final for a single call)
>>> 
>>> Here are a couple of potential ideas on how to represent this (P represents a protocol or class ancestor type):
>>> 
>>> 	varName.P::methodName
>>> 
>>> 	varName.methodName using P
>>> 
>>> 
>>> This is mainly to start a discussion, so feel free to counter-propose a better syntax, etc…
>>> 
>>> It seems fairly straightforward to me. The only objection that I remember coming up when this was discussed before was that the compiler had to keep some information around between modules that it wasn’t keeping around at the time (which is what makes me think it affects the ABI). 
>>> 
>>> One complication which could come up is what happens when P is a variable holding a type instead of a constant type.  There are a few options:
>>> 
>>> 1) Don’t allow such shenanigans (compiler error)
>>> 
>>> 2) Dynamically dispatch based on a runtime check (trap at runtime if P is not an ancestor/conformed-to protocol)
>>> 
>>> 3) Same as 2, except that the protocol conformance uses duck-typing
>>> 
>>> 4) Same as 2/3, except the command is not executed instead of trapping
>>> 
>>> Of those options, 1 is the simplest, but 3 is my favorite, as it is the most powerful (but also has the largest impact on the ABI). 4 could co-exist with 2/3 by adding a ‘?’ variant of the syntax (e.g. varName.P?::methodName)
>>> 
>>> Thoughts?
>> 
>> I think being able to name and call a specific protocol-extension method would be an interesting enhancement.
>> 
>> Being able to bypass another class's overrides and jump to a specific superclass implementation on an arbitrary method call is badly encapsulation-breaking, and I can't think of any OO language with first-class support for it besides C++.  In every other language I know of, super dispatch is always restricted to the self object and only bypasses the overrides of the current class and its subclasses.  Of course there are runtime tricks you can play to get this in, say, ObjC, but I'm not aware of them being frequently used.  I would really to see concrete evidence of this being useful and necessary before considering it any further.
>> 
>> John.
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160819/487e56d9/attachment.html>


More information about the swift-evolution mailing list