Basically you need the block argument to depend on the class of the object that the method is being called on. One way to achieve this is with a protocol that uses Self
:
protocol Writable { }
extension Writable {
// Self can be used in protocols, and point to the concrete implementation
// of the protocol
func write(_ block: ((Self) -> Void) ) throws {
block(self)
}
}
// Just need to declare the conformance, all subclasses will inherit it
class Animal: Writable { }
class Dog: Animal {
var name = "Unnamed"
}
let dog = Dog()
print("Dog name:", dog.name)
try dog.write { $0.name = "Bob" }
print("Dog name:", dog.name)
As expected, the above code will print
Dog name: Unnamed
Dog name: Bob
Note that write
is not part of the protocol requirements, you can add it to the list of protocol methods, however using Self
as part of the protocol requirements will limit the places where the protocol can be used (collections, non-generic function arguments, etc).