Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Class.Type' does not have a member named 'variable' error just a lack of class variable support?

Tags:

xcode

swift

I have been trying to use constants and variables in a class that refer by name to other constants and variables in the same class at the class level. AFAIK, as of Xcode 6 beta 4, Swift still doesn't have class variable support. What I'm wondering is whether the errors I see when trying to refer to other constants (let) or variables (var) are simply due to lack of class variable support?

You can refer to the constants and variables within a method or outside the class, you just don't seem to be able to reference by name at the class level. The following class shows several variations along with the errors you will see displayed in Xcode 6 beta 4.

This can be tested in a playground or regular .swift file.

class Simple {

    let someConstant = 0.50

    var someVariable = 1

    // uncomment let and var lines to see the errors

    // error: 'Simple.Type' does not have a member named 'someConstant'
    // let referringConstant = someConstant
    // error: Use of unresolved identifier 'self'
    // let referringConstant = self.someConstant

    // error: 'Simple.Type' does not have a member named 'someVariable'
    // var referringVar = someVariable
    // error: Use of unresolved identifier 'self'
    // var referringVar = self.someVariable

    // can't do class constants or variables yet either
    // let referringConstant = Simple.someConstant
    // var referringVar = Simple.someVariable

    func simpleMethod() {
        // both of these forms are valid as long as it is unambiguous
        let referToConstant = someConstant
        let referToVariable = someVariable

        var anotherConstant = self.someConstant
        var anotherVariable = self.someVariable
    }
}

For reference, the original Objective-C code that led to this problem in Swift was from the CS193P SuperCard app where a C #define is used for a constant and then that constant is used to set a variable.

@interface PlayingCardView()
@property (nonatomic) CGFloat faceCardScaleFactor;
@end

@implementation PlayingCardView

#pragma mark - Properties

@synthesize faceCardScaleFactor = _faceCardScaleFactor;

#define DEFAULT_FACE_CARD_SCALE_FACTOR 0.90

- (CGFloat)faceCardScaleFactor
{
    if (!_faceCardScaleFactor) _faceCardScaleFactor = DEFAULT_FACE_CARD_SCALE_FACTOR;
        return _faceCardScaleFactor;
}

- (void)setFaceCardScaleFactor:(CGFloat)faceCardScaleFactor
{
    _faceCardScaleFactor = faceCardScaleFactor;
    [self setNeedsDisplay];
}
like image 953
kasplat Avatar asked Jul 22 '14 00:07

kasplat


1 Answers

The two errors messages you're getting are actually a result of two different, but related, reasons.

error: Use of unresolved identifier 'self'

self refers to an instance of a type and does not exist until that type is considered fully initialized, and therefore cannot be used for default property values.

error: 'Simple.Type' does not have a member named 'someConstant'

Class variables and static variables are considered "type variables" of classes and structs, respectively. What this means is that they're defined as variables on the type itself, as opposed to an instance of that type. By this definition and the fact that you can't use self for default property values, it's clear that this error message is a result of Swift looking for a class variable named someConstant. Class variables are still not supported as of Beta 4.

The analogous code for structs, with type variables taken into account, compiles just fine:

struct Simple {
    static let someConstant = 0.50
    static var someVariable = 1

    let referringConstant = someConstant
    var referringVar = someVariable

    let explicitTypeProperty = Simple.someConstant
}

Reference: my recollection of the "Properties" and "Initializers" chapters of The Swift Programming Language.

like image 117
Andrew Avatar answered Nov 16 '22 02:11

Andrew