[swift-evolution] final + lazy + fileprivate modifiers

Goffredo Marocchi panajev at gmail.com
Thu Feb 23 01:18:54 CST 2017


Hey Slava,

> On 22 Feb 2017, at 23:07, Slava Pestov via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>> On Feb 21, 2017, at 4:19 PM, David Waite via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> 
>>> On Feb 21, 2017, at 2:27 AM, Joanna Carter <joanna at carterconsulting.org.uk> wrote:
>>> 
>>> But in the Swift world, we now have the ability to extend almost any type, except Any and AnyObject, which appear to be protected by some deep and dark mechanism within the compiler.  So, just as those two protocols cannot be extended, should we not be looking at some generally available mechanism to prevent extensibility of any type?
>>> 
>>> And, I am not talking visibility here, just extensibility ; somehow those two concerns are often conflated and, I believe, this is the cause of much of the "lively" discussion on visibility specifiers.
>> 
>> This is imho more of an issue with ABI and resiliency. If I can create an extension which adds a method to a type, and that type gains a method with that same signature in a later release, what is the behavior?
> 
> Extension methods are lexically scoped and statically dispatched, so existing code will not be affected by the addition of the new method. New code will call whichever method is visible, or if both are visible in a given lexical scope and overload resolution rules cannot pick an unambiguous winner, the code will no longer type check.

This situation seems pretty messy as, say with a binary framework one day, it may lead to someone conforming to a protocol and implementing a method that will never be called as it is silently overriding a default method only declared in an extension... and there are no warnings for that. 
I think that if the protocol or a protocol extension provides a default implementation a class conforming to it not being allowed to override it may actually help.

Not to mention how for many protocols should be abstract contracts not implementations, I cannot be the only one that enjoys returning to a situation where the code being executed depends on how I dress my instance and not what my instance is:
...objA is an instance of ClassA that conforms to ProtoA which also has a myMethod method and an extension which provides a default implementation of it.

objA.myMethod() 

vs

(objA as ProtoA).myMethod()

When did casting an instance to another type changes what code gets executed became ok and good practice again :)?

Default methods are serving a purpose and are allowing code sharing across structs, but IMHO they cause more harm than good with classes and OOP design while not being a necessary condition for POP either.


> 
> The situation is messier with extensions that add protocol conformances. Right now we don’t do a good job of dealing with duplicate conformances because we assume in several places in the compiler and runtime that they can be looked up globally. We plan on addressing at least some of this.
> 
> Slava
> 
>> 
>>> 
>>>> In C++ terms, it would be when I want some other class to have friend access to a function/data, but for it not to be arbitrarily accessible by subtypes
>>> 
>>> Indeed. I do wonder if some folks approach visibility control as an exercise in "what can I see" whereas, demonstrated by C++ friends, it becomes obvious that it is more about "what do I want to allow to be seen"
>>> 
>>> Is there not a value in forking this discussion into which keywords are truly about visibility control and which are about extensibility control?
>> 
>> Possibly; they are two axes. However, I’m hoping that new access modifiers (including possible submodule functionality) + extensibility modifiers are considered holistically. 
>> 
>> For instance, if there is a feature that allows something comparable to ‘friend’ level access, a restrictive private makes a lot more sense than one with exceptions allowing access to subtypes, within the same file, to extensions, etc. A restrictive, scoped private would be what you use to protect the invariants of your type, with less protected methods given to allow extensions and internal modification safely.
>> 
>> But without a submodule or similar access level, we need a “fileprivate” level access (renamed to ‘private’ or not) to make sure code needing a higher level of access can get it, by being embedded in the same file.
>> 
>>> OK, how does this sound?
>>> 
>>> Extend the 'final' concept, currently used only in classes, to protect any, non-protocol, type from being extended.
>> 
>> The extension mechanism, both being able to add new methods and to conform an existing class to a protocol retroactively, is absurdly powerful. It doesn’t offer any privileged manipulation of types today that would give a safety related reason to restrict it. I’d be reluctant to let someone take that away from me personally without a strong language-level justification (such as needing to restrict it partially to meet ABI/resiliency requirements)
>> 
>> -DW
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> 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