[swift-users] Dealing with loss of observers on protocol properties with default implementations

Neil swift-users at cwbrn.co
Wed Nov 30 11:56:11 CST 2016


Hi folks, 

I'm curious to know how others have handled the loss of property observers when a protocol property has a default implementation. 

For example, consider the following simple protocol declaration:

protocol Widget : class {
    associatedtype IdentifierType
    var identifier: IdentifierType { get set }
}

extension Widget {
    var identifier: IdentifierType {
        get {
            return ... 
        }
        set {
            ... 
        }
    }
}

A class conforming to the Widget protocol cannot leverage property observers on the identifier property without overriding the default implementation:

class WidgetFactory: Widget {
    typealias IdentifierType = Int

    // Overrides the default implementation
    var identifier: Int {
        didSet {
          // ...
        }
    }
}

This is problematic when the default implementation goes beyond merely getting/setting a backing variable. The only solution I've come up with is to mandate a willSet/didSet function pair for each protocol property:

protocol Widget : class {
    associatedtype IdentifierType
    var identifier: IdentifierType { get set }

    func willSetIdentifier(_ newValue: IdentifierType)
    func didSetIdentifier(_ newValue: IdentifierType)
}

extension Widget {
    var identifier: IdentifierType {
        get {
            return ... 
        }
        set {
            ... 
        }
        willSet {
            willSetIdentifier(newValue)
        }
        didSet {
            didSetIdentifier(identifier)
        }
    }
}

I find this to be an ugly solution. Particularly so since non-objc protocols don't support optional members. Compare this to using a base class:

protocol Widget : class {
    associatedtype IdentifierType
    var identifier: IdentifierType { get set }
}

class BaseWidget : Widget {
    typealias IdentifierType = Int

    var identifier: Int {
        get {
            return ...
        }
        set {
            ...
        }
    }
}

class WidgetFactory : BaseWidget {
    // This doesn't override the getter/setter implementation in the base class
    override var identifier: Int {
        willSet {
            ...
        }
    }
}

Has anyone else faced this situation? If so, what was your solution?

-- Neil










More information about the swift-users mailing list