13

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 ...

EDIT:

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
fuzzygoat
  • 26,573
  • 48
  • 165
  • 294
  • `let ammo: Int = StealthFighter.ammunition` maybe... – holex Jun 19 '14 at 15:16
  • note that the object's dynamic type might not be the same as the class the code is in – newacct Oct 01 '14 at 19:33
  • Possible duplicate of [Access static variables within class in Swift](http://stackoverflow.com/questions/29952670/access-static-variables-within-class-in-swift) – mmmmmm May 09 '17 at 23:47

5 Answers5

10

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.

Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
  • 1
    we now have `type(of:)` expression in Swift3 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html – mash Feb 06 '17 at 05:17
3

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

Community
  • 1
  • 1
Anil Varghese
  • 42,757
  • 9
  • 93
  • 110
  • But if all you have is an instance of type Unknown, but you know it conforms to a protocol, how does one access a Type Property? – Ryan Romanchuk Feb 24 '15 at 20:49
3

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.

Kreiri
  • 7,840
  • 5
  • 30
  • 36
3

Swift 4:

var myStealthFighter = StealthFighter()
type(of: myStealthFighter).ammunition
Vlad
  • 6,402
  • 1
  • 60
  • 74
2

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).

Swift Type Properties

“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"

Prine
  • 12,192
  • 8
  • 40
  • 59