In this case, I would think you would move the optional method into a separate 
protocol. If the user implemented the method they would have to explicitly 
conform to this specific protocol in which case they would be treated 
differently. 

Instead of having to check whether someone implemented an optional method in a 
protocol, you would check if they conformed to the protocol that now contains 
it. This is a much stronger contract that is more easily understood by both 
sides.

Daniel 

> On Apr 8, 2016, at 8:47 AM, Jonathan Hull via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> Interesting proposal, but I wanted to mention a couple of potential issues 
> off the top of my head.  I know when I was using optional requirements in 
> Objective C, I would often use the presence/lack of the method (not just 
> whether it returned nil) in the logic of my program.  I used the presence of 
> a method as a way for the implementor of a delegate to naturally communicate 
> whether they wanted a more advanced feature.  The absence of the method 
> itself is information which can be utilized, not just whether it returns nil, 
> and I believe that is part of what people are asking for when they say they 
> want optional methods in Swift.
> 
> 
> Let me try to give a simplified example which I am not sure how you would 
> work around in this proposal:
> 
> Let’s say there is a datasource protocol which optionally asks for an image 
> associated with a particular piece of data (imagine a table or collection 
> view type custom control).  If the method is not implemented in the data 
> source, then a different view is shown for each data point that doesn’t have 
> a place for images at all.  If the method is implemented, but returns nil, 
> then a default image is used as a placeholder instead (in a view which has a 
> place for images).
> 
> tl;dr: Optional methods are often used as customization points, and the 
> methods, if implemented, may also have another meaning/use for nil.
> 
> 
> Similarly, a different back-end implementation may be used in the case where 
> an optional method is not implemented.  Let’s say you have something like a 
> tableview with an optional method giving rowHeights.  If that method is 
> unimplemented, it is possible to have a much more efficient layout algorithm… 
> and in some cases, you may check for the existence of the optional method 
> when the delegate is set, and swap out a different layout object based on 
> which customizations are needed (and again nil might mean that a 
> height/etc... should be automatically calculated).  This is the ability I 
> miss the most.
> 
> 
> Not saying the proposal is unworkable, just wanted to add some food for 
> thought.  I know I really miss optional methods in Swift.  In some areas 
> Swift is a lot more powerful, but there are lots of things I used to do in 
> Obj C that I haven’t figured out how to do in Swift yet (if they are even 
> possible).  I am kind of disturbed by the trend/desire to get rid of the 
> smalltalk-ness, as opposed to finding new and safer ways to support that 
> flexibility/expressiveness.  I would really like to see swift deliver on it’s 
> promise of being a more modern alternative to ObjC (which it isn’t yet, IMHO) 
> instead of just a more modern alternative to C++/Java.
> 
> Thanks,
> Jon
> 
>> Proposed Solution: Caller-side default implementations
>> 
>> Default implementations and optional requirements differ most on the caller 
>> side. For example, let’s use NSTableView delegate as it’s imported today:
>> 
>> func useDelegate(delegate: NSTableViewDelegate) {
>>   if let getView = delegate.tableView(_:viewFor:row:) { // since the 
>> requirement is optional, a reference to the method produces a value of 
>> optional function type
>>     // I can call getView here
>>   }
>> 
>>   if let getHeight = delegate.tableView(_:heightOfRow:) {
>>     // I can call getHeight here
>>   }
>> }
>> 
>> With my proposal, we’d have some compiler-synthesized attribute (let’s call 
>> it @__caller_default_implementation) that gets places on Objective-C 
>> optional requirements when they get imported, e.g.,
>> 
>> @objc protocol NSTableViewDelegate {
>>   @__caller_default_implementation func tableView(_: NSTableView, viewFor: 
>> NSTableColumn, row: Int) -> NSView?
>>   @__caller_default_implementation func tableView(_: NSTableView, 
>> heightOfRow: Int) -> CGFloat
>> }
>> 
>> And “optional” disappears from the language. Now, there’s no optionality 
>> left, so our useDelegate example tries to just do correct calls:
>> 
>> func useDelegate(delegate: NSTableViewDelegate) -> NSView? {
>>   let view = delegate.tableView(tableView, viewFor: column, row: row)
>>   let height = delegate.tableView(tableView, heightOfRow: row)
>> }
>> 
>> Of course, the code above will fail if the actual delegate doesn’t implement 
>> both methods. We need some kind of default implementation to fall back on in 
>> that case. I propose that the code above produce a compiler error on both 
>> lines *unless* there is a “default implementation” visible. So, to make the 
>> code above compile without error, one would have to add:
>> 
>> extension NSTableViewDelegate {
>>   @nonobjc func tableView(_: NSTableView, viewFor: NSTableColumn, row: Int) 
>> -> NSView? { return nil }
>>   
>>   @nonobjc func tableView(_: NSTableView, heightOfRow: Int) -> CGFloat { 
>> return 17 }
>> } 
>> 
>> Now, the useDelegate example compiles. If the actual delegate implements the 
>> optional requirement, we’ll use that implementation. Otherwise, the caller 
>> will use the default (Swift-only) implementation it sees. From an 
>> implementation standpoint, the compiler would effectively produce the 
>> following for the first of these calls:
>> 
>> if delegate.responds(to: 
>> #selector(NSTableViewDelegate.tableView(_:viewFor:row:))) {
>>   // call the @objc instance method with the selector 
>> tableView:viewForTableColumn:row:
>> } else {
>>   // call the Swift-only implementation of tableView(_:viewFor:row:) in the 
>> protocol extension above
>> }
>> 
>> There are a number of reasons why I like this approach:
>> 
>> 1) It eliminates the notion of ‘optional’ requirements from the language. 
>> For classes that are adopting the NSTableViewDelegate protocol, it is as if 
>> these requirements had default implementations.
>> 
>> 2) Only the callers to these requirements have to deal with the lack of 
>> default implementations. This was already the case for optional 
>> requirements, so it’s not an extra burden in principle, and it’s generally 
>> going to be easier to write one defaulted implementation than deal with it 
>> in several different places. Additionally, most of these callers are 
>> probably in the Cocoa frameworks, not application code, so the overall 
>> impact should be small.
>> 
>> Thoughts?
>> 
>>      - Doug
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to