Class Properties


(Genaro Chris) #1

Why can't we use class stored properties in swift language or is it a bug?


(Svein Halvor Halvorsen) #2

You can certainly use class stored properties in Swift.
Please provide more context.


(Tino) #3

@Genaro-Chris is right - at least for the version of Swift bundled with current Xcode:

class X {
class let x = 4
}

-> error: class stored properties not supported in classes; did you mean 'static'? (it's the same for var)

I guess this is intentional, because it might be confusing when each subclass gets its own property.

But imho it gets strange when you try this with a struct:
class properties are only allowed within classes; use 'static' to declare a static property


(Joanna Carter) #4

So use static instead of class. As long as you don't intend to override them in subclasses, no problem. As for structs, class vars do not apply since they are not classes


(Svein Halvor Halvorsen) #5

Ah. Thanks for the clarification. I now understand OP’s issue. static probably works.


(Anthony Latsis) #6

The error is correct, stored properties cannot be overriden, because there's nothing to override. For a property to be overridable, it has to be a computed property (it must have some behavior that you would want to override):

class A {
    class var foo: Int { return 0 }
}

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

@Genaro-Chris This is why you can't have a stored type property prefixed with class, which denotes that it can be overriden. But as people mention, you can have it static.

This only applies to constant stored properties. See the answer below.


(Hamish Knight) #7

stored properties cannot be overriden, because there's nothing to override.

That's not correct, stored properties can be overriden as they have implicitly generated accessors. This can be seen with instance stored properties:

class C {
    var foo = 0
}

class D : C {
    override var foo: Int { 
        get { return 1 }
        set { print(newValue) }
    }
}

let d = D()
print(d.foo) // 1

IMO it makes sense to support stored class properties – they should have the semantics of a computed class property with a static backing variable.

For example:

class C {
    class var foo = 0
}

should be equivalent to:

class C {
    static var _foo = 0
    class var foo: Int {
        get { return _foo }
        set { _foo = newValue }
    }
}

(Anthony Latsis) #8

Thanks for reacting, I honestly had no idea about that. But now that I follow your logic about accessors, the restrictions on overriding let cease to make sense.


(Hamish Knight) #9

let properties are slightly different, as they carry the additional promise that their value remains constant after initialisation. Allowing them to be overridden could violate this, which is why it’s forbidden (it’s also why computed get-only properties are denoted with var rather than let).

I didn’t consider it at the time, but I guess this means that if class stored properties were allowed, then class let would be equivalent to static let.


(Michel Fortin) #10

I can guess the reasoning behind the current behavior is like this: you can add methods to a meta-class, but you can't add storage. Static variables are not stored in the meta-class instance, but as global variables. Whether that technical detail about the underlying implementation should leak into the language is a good topic,

On a tangent, I think class and static are a bit too similar and can easily be confused. I wish only one was allowed and we could simply use final to denote properties and methods that shouldn't be overridden.


(Anthony Latsis) #11

I understand the convention, either way it would be too late to discuss such disruptive changes. But I was thinking we could have had overridable lets that could be final, which IMO makes more sense and sounds more consistent, even though we can mimic the behaviour with constant get-only computed properties. Besides, as long as it’s a let, we would still be keeping the promise regardless of whether it is overridden or not, wouldn’t we?

@michelf
Regarding class and static, the convention is that type properties are non-overridable by default, whereas instance properties are overridable by default. This implies opposite mechanisms for managing overridability: we use final to restrict overridability on instance properties and class to, conversely, allow it on type properties.


(Michel Fortin) #12

What makes static the default vs. class? To me, they look pretty much on equal footing, except perhaps when it comes to stored property (which aren't allowed to be class).


(Joanna Carter) #13

class is a special case of static, only applicable where you are planning on working with class hierarchies, where you want to override a base class's static behaviour (as long as it doesn't involve stored properties)