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];
}
The two errors messages you're getting are actually a result of two different, but related, reasons.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With