For the record, the thing optional implementations have (at least for methods) that default implementations don't is checking whether a type has provided an explicit implementation. Which you can mimic and make more flexible with default implementations:
// Before
protocol MyDelegate: AnyObject {
optional func myView(_ myView: MyView, processInput input: String) -> String
}
// After
protocol MyDelegate: AnyObject {
func myView(_ myView: MyView, processInput input: String) -> String?
}
extension MyDelegate {
func myView(_ myView: MyView, processInput input: String) -> String? { nil }
}
"But that's not the same thing at all!" Yes, it's more flexible, even! It lets a delegate log the input or whatever, but defer to the original object for processing by returning nil anyway.
"But the return type was already optional!" You have the option (heh) to nest optionals, or use a bespoke enum for less confusion, but consider whether you really need to distinguish nil
from "unimplemented". Sometimes you do! But usually it was going to be your default anyway.
"But I don't have a return value!" Use Bool, or Void?
if you want behavior like @objc optional
.
"But I wanted to use a property!" Swift already kind of bungles imported ObjC optional properties, since there isn't a separate "call" step when you use them. If your property has a setter, I don't really have a good answer for you. (But part of the reason optional properties are bungled is because we didn't have a good answer for those either.)
"But I wanted to save the cost of a call!" Eh, I guess? That's probably not an issue in practice in most cases. Testing whether a requirement is missing is about third of the cost of calling anyway (extremely rough numbers, depends somewhat on the argument types, etc).
"But I really do want to distinguish whether the default implementation is being used." I've seen a very small number of legitimate use cases for this, the main one being changing the default behavior without affecting those who have manually customized. That's an iffy thing to do in general, but it's something that could be added to the language without calling it optional
and affecting the main path (as a run-time reflective capability, basically).
"But that's really verbose!" Yeah, this one I'll agree with. Way way back, we talked about being able to write unconstrained default implementations in the main protocol
declaration; that would help. Macros could potentially also help, though I hesitate to lean on them due to the compilation time concerns.
"But that's not satisfying!" Entirely subjective—your opinion is as valid as mine—so I can't argue