> On Jun 12, 2016, at 9:08 PM, Charlie Monroe <char...@charliemonroe.net> wrote:
>> On Jun 11, 2016, at 3:51 AM, Andrew Bennett via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> Unavailable doesn't mean un-callable.
>> If you're marking an override or required initialiser as unavailable, it's 
>> still possible it's called dynamically, or by super.
>> If you're marking it unavailable for some OS versions, it could still be 
>> called by the other OS versions.
>> If it's neither of those two categories, you probably don't even need the 
>> function declaration.
>> It's not clear what default behaviour you would want in an unavailable 
>> method, calling super, calling a new method, a runtime error, ...
>> 
>> An undefined implementation lacks clarity, as Erica says, "this is an 
>> example where concision is overrated".
>> 
>> Likewise, as Brent says, you may want the old unavailable API to call 
>> through to the new API.  A new version of a library may be dynamically 
>> linked by something compiled against an older version.

> As Andrew says - I have several cases where I mark a method on a subclass as 
> unavailable to ensure subclasses do not call it directly, but it is required 
> by the root class to be implemented (which it is and gets called).
> 
> Example:
> 
> class Root {
>       func doSomething() {
>               print("Root")
>       }
> }
> 
> class Subclass {
>       @available(*, unavailable)
>       override func doSomething() {
>               super.doSomething()
>               print("Subclass")
>       }       
> }
> 
> And you can still do:
> 
> let instance: Root = Subclass()
> instance.doSomething()
> 
> and it will call Root Subclass.
> 
> If it's renamed, you should really first deprecate it and just call the new 
> API and after a while make it unavailable with no change in the code.
> 
> If it's meant for abstract classes, then it's kind of a different issue.

In many of the cases you guys are describing, we ought to have enough 
information to do the right thing.  For example, library evolution shouldn't be 
done with an ordinary unavailable attribute; it should use something that 
indicates that the API was added in v2.6c, deprecated in v2.7, and made illegal 
in v2.8.  With that information, we clearly would still require a function body 
if the build configuration says that we need to support pre-v2.8 clients.

My point was just that there is a clear use case for an attribute that says 
"don't allow this declaration to be used at all", including indirectly such as 
via a protocol requirement or overridden method, and those use cases should not 
require an actual function body.  I recognize that there are also use cases for 
a more relaxed attribute that just prohibits direct uses but still requires a 
function body.  Perhaps that should just be a completely different attribute, 
or perhaps we can differentiate based on the attribute arguments, or perhaps we 
can address all of those use cases with targeted language features.  However, 
we should still get to a point where we don't require function bodies for the 
true-unavailable cases.

John.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to