Reputation: 26223
I am not sure is this is correct behaviour or if its unintended. I have setup StealthFighter
so that it returns a class type computed property variable called ammunition
.
func globalTests() {
println("globalTests")
println("AMMUNITION: \(StealthFighter.ammunition)")
var myStealthFighter = StealthFighter()
println("MISSILES: \(myStealthFighter.missiles)")
println("AMMUNITION: \(myStealthFighter.ammunition)") // ERROR
}
class StealthFighter {
class var ammunition:Int {
return 500;
}
var missiles: Int = 5
}
When directly accessing the class StealthFighter
this works fine and returns 500 as expected. But if I create and instance myStealthFighter
and then try and access the class property on the instance I get the error: 'StealthFighter' does not have a member named 'ammunition'
I can't find any mention of this, I am assuming from this that class properties are accessible only via the class? and not on any instances created from it? I just want to make sure I am understanding this correctly ...
So I have probably worded the type variable name wrong as it should probably be maxAmmunition
to signify that StealthFighters
can only take 500 rounds. I can see the point, if you want the maxAmmunition
for the class then you ask the class.
As @Kreiri and @0x7fffffff points out it does seem that you can ask the instance what the class ammunition (or maxAmmunition) is by using dynamicType.
println("CLASS - AMMUNITION: \(StealthFighter.ammunition)")
var myStealthFighter = StealthFighter()
println("INSTA - AMMUNITION: \(myStealthFighter.dynamicType.ammunition)")
.
// OUTPUT
// CLASS - AMMUNITION: 500
// INSTA - AMMUNITION: 500
Upvotes: 13
Views: 7743
Reputation: 6732
Swift 4:
var myStealthFighter = StealthFighter()
type(of: myStealthFighter).ammunition
Upvotes: 3
Reputation: 130193
Your assumption is correct. Type variables are only meant to be accessed directly from the class. If you want to get at them from an instance, you can do so by accessing the dynamicType property on your instance, like so.
let theFighter = StealthFighter()
let missiles = theFighter.dynamicType.missiles
println(missiles)
However, I don't think that this is the correct approach for you to be taking here. Assuming that you want to have one class "StealthFighter", and possibly multiple instances of that class, each with the ability to have its own number of missiles independent of the others, you should probably make this an instance variable by simply ditching the class keyword.
Upvotes: 10
Reputation: 42977
These properties are known as Type properties
in swift. It should be called on its type
ie class name, not on instance. Type properties holds same value across all the instances of the class just like static constant in C.
Querying and Setting Type Properties
Type properties are queried and set with dot syntax, just like instance properties. However, type properties are queried and set on the type, not on an instance of that type
Excerpt from : swift programming language
Upvotes: 3
Reputation: 7850
dynamicType
allows access instance’s runtime type as a value, so accessing class property from instance would look like this:
var myStealthFighter = StealthFighter()
myStealthFighter.dynamicType.ammunition
Works in playground, at least.
Upvotes: 3
Reputation: 12528
Yes. This is a correct behaviour. These Type Properties
can only be accessed over the Type and are not available on the instance itself.
In the Swift Book from Apple it is described in the section "Type Properties" (Page 205).
“Unlike stored instance properties, you must always give stored type properties a default value. This is because the type itself does not have an initializer that can assign a value to a stored type property at initialization time"
Upvotes: 2