> On Jan 5, 2017, at 9:30 AM, Brian King <[email protected]> wrote:
>
> +1, I really like the consistency. There's still one potential inconsistency
> that I think could be changed to improve things
> Overriding of declarations introduced in class extensions
>
> The inference of @objc inside extensions in Swift 3 is more than visibility
> to the Obj-c runtime, it also infers `dynamic`. This proposal appears to
> retain that, since `@objc` in an extension would allow override via message
> dispatch, where as `@objc` in a class declaration would only make the
> selector available to the obj-c runtime and retain table dispatch.
Excellent point! I’d come across the `dynamic` inference while writing this
proposal, but had deluded myself into thinking that it was just an
implementation detail. You’re right that it surfaces in the user model.
>
> Does it make sense to remove the `dynamic` inference too? This would force
> all extension methods that can be overridden to be declared `@objc dynamic`.
> This clarifies the purpose of @objc since it only manages Obj-C visibility,
> and does not modify dispatch behavior.
The practical effect of removing `dynamic` inference is that a declaration
introduced in a class extension can only be overridden if it is marked
@objc dynamic
Overriding declarations won’t have to repeat this utterance (“override”
suffices), so the boilerplate is restricted to the introduction of the first
overridable declaration.
I guess the specific rule would be that @objc declarations introduced in a
class extension must either be ‘dynamic’ or ‘final’, with the
subtle-but-understandable annoyance that ‘final’ methods can still be swizzled
by the Objective-C runtime.
I definitely need to mention this in the proposal (thank you!), but I’m on the
fence regarding whether to propose doing anything about it in this specific
proposal. I already intentionally subsetted out the other part of the
overrides-of-declarations-in-extensions issue (see the section “Overriding of
declarations introduced in class extensions”), and it feels like the issues
should be tackled together.
Part of me also wonders whether it’s worth this level of boilerplate now to
save on an expected-to-be-small amount of breakage later. Specifically, we’re
talking about cases where the user swizzled a method but didn’t mark it
‘dynamic’. Or, swizzled a method that was explicitly marked ‘final’, which the
runtime doesn’t know. There are numerous other failure cases here where one has
swizzled a method via the Objective-C runtime such that only Objective-C
callers invoke the new method, but Swift callers invoke the pre-swizzled
version. Personally, I think we can address this problem holistically by
teaching the Objective-C runtime about Swift’s thunks so it can warn when
swizzling non-‘dynamic’ ones, which would obviate the need for explicit
‘dynamic’ in these cases.
> I know this departs from my previous "NSObject should stay dynamic" argument
> earlier, but I was mostly arguing for consistency. Since it is clear that
> dynamic behavior should be opted into, I think forcing an additional
> `dynamic` keyword seems to make sense. Some developers may rely on this
> implicit `dynamic` behavior and encounter issues if a future version of swift
> allows overrides in extensions via table dispatch.
We’re both seeking a more consistent and predictable model, but we’re going in
different directions. I feel that my proposal is more in line with the
direction Swift has been going.
- Doug
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution