[Idea] How to eliminate 'optional' protocol requirements


(Anton Zhilin) #1

Here is how I would like this to be implemented.

1. Optional method requirements will be represented in Swift as methods
having import-only attribute @optional and defaulted to be fatalError()

2. On the inside, this default implementation will not define a method.
These objects will not respond to corresponding selector unless the default
implementation is overridden.

3. Calls from Swift side will turn into checks with fatalError()

4. The only way to check existence of such method from Swift will be
`responds(to: Selector)`

Example:

// Objective-C protocol is imported as:
protocol NSTableViewDelegate {
@optional func tableView(_: NSTableView, viewFor: NSTableColumn, row: Int)
-> NSView?
@optional func tableView(_: NSTableView, heightOfRow: Int) -> CGFloat
}
extension NSTableViewDelegate {
@optional func tableView(_: NSTableView, viewFor: NSTableColumn, row: Int)
-> NSView? {
fatalError("Unimplemented")
}
@optional func tableView(_: NSTableView, heightOfRow: Int) -> CGFloat {
fatalError("Unimplemented")
}
}

class MyDelegate : NSTableViewDelegate {
@optional func tableView(_: NSTableView, viewFor: NSTableColumn, row: Int)
-> NSView? {
//...
}
}

getTableViewDelegate().tableView(x, heightOfRow: y) // will fatalError() if
not responds to selector
if getTableViewDelegate().responds(to: #selector(...)) { ... }

- Anton


(Andrew Bennett) #2

For a while I've thought it would be useful to have a way to refer to the
protocol's default implementation, even when you provide your own. We could
possibly do away with most people's concerns and optional methods if we
could do something like this:

if MyProtocol.someMethod === Self.someMethod {
}

···

On Sunday, 10 April 2016, Антон Жилин <swift-evolution@swift.org> wrote:

Here is how I would like this to be implemented.

1. Optional method requirements will be represented in Swift as methods
having import-only attribute @optional and defaulted to be fatalError()

2. On the inside, this default implementation will not define a method.
These objects will not respond to corresponding selector unless the default
implementation is overridden.

3. Calls from Swift side will turn into checks with fatalError()

4. The only way to check existence of such method from Swift will be
`responds(to: Selector)`

Example:

// Objective-C protocol is imported as:
protocol NSTableViewDelegate {
@optional func tableView(_: NSTableView, viewFor: NSTableColumn, row:
Int) -> NSView?
@optional func tableView(_: NSTableView, heightOfRow: Int) -> CGFloat
}
extension NSTableViewDelegate {
@optional func tableView(_: NSTableView, viewFor: NSTableColumn, row:
Int) -> NSView? {
fatalError("Unimplemented")
}
@optional func tableView(_: NSTableView, heightOfRow: Int) -> CGFloat {
fatalError("Unimplemented")
}
}

class MyDelegate : NSTableViewDelegate {
@optional func tableView(_: NSTableView, viewFor: NSTableColumn, row:
Int) -> NSView? {
//...
}
}

getTableViewDelegate().tableView(x, heightOfRow: y) // will fatalError()
if not responds to selector
if getTableViewDelegate().responds(to: #selector(...)) { ... }

- Anton