With the transition from Swift 2 -> 3 I’ve started running into one particular
issue VERY often (although it’s not necessarily specific to the transition). If
a protocol method is optional (either because it is an @objc optional or
because it has a default implementation) there is a risk that the conformer
will have a misspelled or slightly incorrectly typed implementation of the
method. For instance:
protocol RouteDestinationViewController: class {
static func viewController(with url: URL, properties: [String:String])
-> UIViewController?
}
extension RouteDestinationViewController where Self: UIViewController {
static func viewController(with url: URL, properties: [String:String])
-> UIViewController? {
return Self.init()
}
}
class FooController: UIViewController, RouteDestinationViewController {
static func viewController(with url: URL, properties: [String:Any]) ->
UIViewController? {
return FooController(properties: properties)
}
}
Notice the issue there? Properties is supposed to be [String:String], but
FooController uses [String:Any] (this is an exact issue I ran into after a
small refactor). When viewController(with:properties:) is called, it will use
the default implementation instead of what the compiler sees as a completely
different method. Over the betas the compiler has gotten better warnings about
this, but is still not 100%.
Other cases of this issue are common with imported ObjC protocols that have
different naming in Swift. In some cases an @objc name must be applied to
ensure it is declared in a way that the protocol can see it.
We solve this problem with subclassing by requiring “override”. If the override
keyword is present but the superclass doesn’t have a matching method, the
compiler warns us about it. Similarly if the superclass implements the same
method and the subclass doesn’t include override, we get a warning so that it
is clear that you are overriding behavior.
For protocols, I don’t think a required keyword would be the best approach.
It’s a completely valid case that a type could conform to a protocol using
existing methods, perhaps even from a different module. Further, a single
method could satisfy multiple protocols, and be overriden from a superclass.
What I would propose would be something like an optional override(<#protocol
name#>). Something like the following:
override(RouteDestinationViewController) static func
viewController(with url: URL, properties: [String:Any]) -> UIViewController? {
return FooController(properties: properties)
}
A method should be able to include multiple overrides (including a bare
override to indicate that it is overriding a class method).
Thoughts? Are you seeing similar issues?
David Beck
http://davidbeck.co
http://twitter.com/davbeck
http://facebook.com/davbeck
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution