> On Apr 1, 2016, at 5:37 PM, 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.
Interesting point.
>
> 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.
It’s “each" call site, not “the” call site. If there are multiple call sites,
we’d presumably want to factor out the default behavior computation anyway.
> 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.
This is what concerns me most. Delegate protocols tend to grow large over time
(for good reason), and having a large family of related protocols is hard to
navigate.
- Doug
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution