How to store constants at the class level that can be overriden?

71 views Asked by At

I want to write the following in Swift:

class A
{
    class let x = 0
    func print_class_property()
    {
        print(type(of: self).x)
    }
}

class B:A
{
    overriding class let x = 1
}

class C:A
{
    overriding class let x = 5
}

A().print_class_property() // 0
B().print_class_property() // 1
C().print_class_property() // 5

But of course, this doesn’t compile.

Instead, I can demote the class property to a variable instance property that’s overwritten in the subclass initializers, but this allocates storage for x in every instance of A, B, or C. In addition you lose the guarantee that x never changes across the lifetime of the object.

How do I store constants at the class level, that can be shared by all instances of a subclass?

1

There are 1 answers

12
OOPer On

Unfortunately Swift (as for now) cannot have class stored properties that can be overriden. But can have class computed properties, which are overridable.

You can write something like this:

class A
{
    class var x: Int {
        return 0
    }
    func print_class_property()
    {
        print(type(of: self).x)
    }
}

class B:A
{
    override class var x: Int {
        return 1
    }
}

class C:A
{
    override class var x: Int {
        return 5
    }
}

A().print_class_property() //->0
B().print_class_property() //->1
C().print_class_property() //->5

ADDITION

If you do not desire such re-evaluation as noted in comments, you may need to have some another static property.

For example:

class A
{
    class var x: SomeLargeObject {
        struct My {
            static let obj = SomeLargeObject("abc", 0)
        }
        return My.obj
    }
    func print_class_property()
    {
        print(type(of: self).x)
    }
}

class B:A
{
    override class var x: SomeLargeObject {
        struct My {
            static let obj = SomeLargeObject("def", 1)
        }
        return My.obj
    }
}

class C:A
{
    override class var x: SomeLargeObject {
        struct My {
            static let obj = SomeLargeObject("ghi", 5)
        }
        return My.obj
    }
}