Abstract methods and protocol extensions

Now that Swift has protocol extensions, is there anything that abstract methods would provide that can't be achieved with protocol extension?

Replies

It is currently not possible to define nested types within protocols (even within protocol extensions).

I don't know if this is intentional or simply not implemented yet, but it's the only thing currently preventing me from being able to elegantly use protocols this way (I want to define `ErrorType` enums within the protocol for conforming classes to use).

While you can require a conforming type to have a particular property, you can't actually declare and allocate storage for that property just by conforming to a protocol, while you can do that by inheriting from a class.


Let me explain what I mean. I have a protocol that creates a linked list of handlers:


protocol HandlerType: class {
   var nextHandler: HandlerType? { get set }
   func handleThing(thing: Thing)
}

extension HandlerType {
   func insertHandler(handler: HandlerType) {
        handler.lastHandler.nextHandler = self.nextHandler
        self.nextHandler = handler
    }
    var lastHandler: HandlerType {
         return nextHandler?.lastHandler ?? self
    }
}


There's nothing about nextHandler's behavior that needs be customized by any HandlerType. It should always be a stored property, be gettable by anybody but set only by the insertHandler(_:) method, should not have property observers, and should never be customized by the handler in any way. Managing nextHandler is rightly HandlerType's responsibility. But when I go to implement a class conforming to HandlerType, I have to explicitly redeclare nextHandler, and nothing prevents me from redeclaring it as a computed property or attaching a dubious didSet handler. Nor does anything stop me from setting it in any code anywhere in my app.


If, on the other hand, I used an abstract class:


class Handler {
    private(set) final var nextHandler: Handler?
     
    func handleThing(thing: Thing) {
         fatalError("Class \(self.dynamicType) does not implement handleThing(_:)")
    }
    final func insertHandler(handler: Handler) { ...as above... }
    final var lastHandler: Handler { ...as above... }
}


Then the management of nextHandler is completely controlled and encapsulated by Handler. None of its subclasses need ever think about how nextHandler is managed; none of them can even tamper with that logic if they want to. It's simply not their concern.


That's one thing that an abstract class can do but a protocol extension never can. It's a little bit of a quirky case, I admit, but it's a design decision I'm facing at this very moment.