Why can't a subclass use didSet to observe parent's private(set) properties?

This seems to be a very valid use case where you need to act upon the parent's property changes at the earliest possible moment:

import GameplayKit

class GameCoordinator: GKStateMachine {
    // ❗️ Cannot observe read-only property 'currentState'; it can't change
    open override var currentState: GKState? { 
        didSet {
            // ❗️ Ambiguous use of 'currentState'
            print("currentState: ", oldValue, " → ", currentState) 

Obviously, GKStateMachine.currentState can and does change, but there's no sane point in GKStateMachine to hook into to act exactly when it changes; I can only override the point before it may change.

Note: This post is not about seeking solutions for the GKStateMachine-related issue; it's meant as an example.

There are other such cases where the ability to observe a parent's read-only properties would be useful.

Now, of course, this wouldn't make sense for computed properties, so they should be distinguished from private(set) properties for this feature.

Do you have a different example, because yours is invalid as currentState is indeed get only and therefore probably either a computed property or it hides its setter?! The latter shouldn‘t be exposed to user.

If the property were KVO-compatible, one would be able to observe changes, even if the setter is private. Why should Swift not support the same for willSet and didSet? I could buy the argument that whether there's a setter at all should be hidden, but that doesn't seem to be what you're saying.

I think the issue here is that a subclass generally doesn't (and shouldn't?) know if the property is in fact a stored or a computed property. Computed properties can obviously not be observed in this manner.

private(set) behaves like a completely private stored property and an additional non-private computed property, and that's fine imo. I think it would be weird if subclasses could suddenly subscribe to changes of a private stored property of a superclass without the superclass explicitly supporting this behavior.

1 Like

I think because it's private(set) the subclass just can't "see" that there is a setter.

What would be needed is a protected(set) then only the subclass would know it is settable. But I doubt this feature would ever get added given the general disdain of class inheritance..

1 Like

And then the subclass would actually be able to set the property as well, which is something we generally want to avoid when using private(set).

public private(set) internal(didSet) fileprivate(willSet) var x: Int


1 Like