-1 I hope that default implementations living in the protocol will address this. I would even prefer to move in 'the other direction' and have optional methods on protocols come into swift as default implementations. TJ
On Sat, Apr 2, 2016 at 6:07 AM, Brent Royal-Gordon via swift-evolution < [email protected]> wrote: > > Protocol requirements with default (no-op) implementations already > satisfy that design goal, no? > > Kind of. If I may steelman* optional members for a moment... > > In cases where a default implementation would do, the default > implementation will usually also be the behavior you want for a nil > instance, but there's no convenient way to share logic between the two. For > example, consider this: > > protocol UITableViewDelegate { > ... > func tableView(_ tableView: UITableView, > heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat > } > extension UITableViewDelegate { > func tableView(_ tableView: UITableView, > heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { > return tableView.rowHeight > } > } > > class UITableView { > ... > private func addRow(at indexPath: NSIndexPath) { > ... > cell.size.height = delegate?.tableView(self, > heightForRowAtIndexPath: indexPath) ?? rowHeight > ... > } > ... > > You have to duplicate the default logic both in the default implementation > and at the call site, but there is no convenient way to share it—the > extension method can't call into an expression at some call site, and > contrarily the call site can't invoke the default logic from the extension. > > If the method were optional, then optional chaining would solve this > problem for us: > > protocol UITableViewDelegate { > ... > optional func tableView(_ tableView: UITableView, > heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat > } > > class UITableView { > ... > private func addRow(at indexPath: NSIndexPath) { > ... > cell.size.height = delegate?.tableView?(self, > heightForRowAtIndexPath: indexPath) ?? rowHeight > ... > } > ... > > This way, there is only one source of default behavior: the call site. > > I'm also concerned by the thought of just how many sub-protocols we might > end up with. When I try to fully factor NSTableViewDelegate (as it > currently exists in the headers), I end up with ten protocols: > > NSTableViewDelegate > - tableView:willDisplayCell:forTableColumn:row: > > NSTableViewLayoutDelegate: NSTableViewDelegate > - tableView:heightOfRow: > > NSTableViewRowSelectionDelegate: NSTableViewDelegate > - tableView:shouldSelectRow: > - selectionShouldChangeInTableView: > - tableViewSelectionIsChanging: > - tableViewSelectionDidChange: > - tableView:shouldTrackCell:forTableColumn:row: (10.5) > - tableView:selectionIndexesForProposedSelection: (10.5) > > NSTableViewTypeSelectDelegate: NSTableViewDelegate (10.5) > - tableView:typeSelectStringForTableColumn:row: > - tableView:nextTypeSelectMatchFromRow:toRow:forString: > - > tableView:shouldTypeSelectForEvent:withCurrentSearchString: > > NSTableViewToolTipDelegate: NSTableViewDelegate > - > tableView:toolTipForCell:rect:tableColumn:row:mouseLocation: > > NSTableViewColumnDelegate: NSTableViewDelegate > - tableView:shouldEditTableColumn:row: > - tableView:shouldSelectTableColumn: > - tableView:mouseDownInHeaderOfTableColumn: > - tableView:didClickTableColumn: > - tableView:didDragTableColumn: > - tableViewColumnDidMove: > - tableViewColumnDidResize: > - tableView:sizeToFitWidthOfColumn: (10.6) > - tableView:shouldReorderColumn:toColumn: (10.6) > > NSTableViewCellExpansionDelegate: NSTableViewDelegate (10.5) > - tableView:shouldShowCellExpansionForTableColumn:row: > > NSTableViewCustomCellDelegate: NSTableViewDelegate (10.5) > - tableView:dataCellForTableColumn:row: > - tableView:isGroupRow: > > NSTableViewCellViewDelegate: NSTableViewDelegate (10.7) > - tableView:viewForTableColumn:row: > > NSTableViewRowViewDelegate: NSTableViewDelegate (10.7) > - tableView:rowViewForRow: > - tableView:didAddRowView:forRow: > - tableView:didRemoveRowView:forRow: > - tableView:rowActionsForRow:edge: (10.11) > > Some of these are probably unnecessary; they could be merged into > NSTableViewDelegate and given default implementations. But at least a few > of them would be very much needed. Would users be able to navigate this > mess? Would they discover the features tucked away in sub-protocols? I'm > just not sure. > > And of course the safety issues that make optional protocol members > dangerous in Objective-C don't exist in Swift. Swift will force you to test > for the presence of an optional member; you can't carelessly call one. > > (Incidentally, resilience might also benefit from supporting optional > protocol members and adding a `public(optional)` feature which made all > call sites outside the resilience domain treat all members as optional. You > could then mark protocols meant to be called only by clients inside the > resilience domain—like data sources and delegates—with `public(optional)` > and gain the ability to delete obsolete members.) > > > > * Steelmanning is the opposite of strawmanning. > > -- > Brent Royal-Gordon > Architechies > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
