ref –
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html
http://stackoverflow.com/questions/24018327/what-does-an-exclamation-mark-mean-in-the-swift-language
https://mikeash.com/pyblog/friday-qa-2014-06-20-interesting-swift-features.html
Declaring Properties
Implicit Optional type
The existence of NULL in C (nil in Objective-C) means that all pointer types in the language are implicitly optional types. If you have a NSString *, it means “pointer to NSString, or nil”. If you have a char *, it means “pointer to char, or NULL”.
The existence of NULL in C blows apart the entire static type system when it comes to pointers. Every pointer type is a half truth. Whenever you see a type “pointer to X”, there’s always an implied “…or NULL.”
Swift approaches this in a consistent manner by making all types non-optional, and allowing any type to be made optional with an additional annotation.
nonOptStr String is the default behavior that Swift wants to do.
optStr is the optional type that can contain either nil or the String in our case, and the additional annotation is the “?”.
1 2 |
var optStr: String?, var nonOptStr: String |
Here, a is a plain Int and it always contains some integer value. b is an optional Int and it either contains an integer value, or it contains nothing.
1 2 |
var a: Int var b: Int? |
If a parameter can accept nil, then it will be declared as an optional type. If it can’t, it won’t. The compiler can easily check your code to make sure it’s doing the right thing. Likewise, if a return value can be nil, it will be an optional type, making it obvious. In the common case, your types will be non-optional, making it clear that they always hold something.
Optional Binding
This is to safely display your optional value. If its nil, you can specify an error block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var x: Int?; // declare OPTIONAL VARIABLE X! x = 45; // set optional variable // When "wrapped", the value of an Optional variable is an enum with two possible values (a little like a Boolean). // This enum describes whether the variable holds a value (Some(T)), or not (None). // thus, you will see the value of the Optional variable get evaluated in this // if/else statement. If its Some(T), then it gets printed. If (Non), then we display ERROR MESSAGE. //OPTIONAL BINDING if let tempX = x { print(tempX); } else { print("uh oh, x is NOT VALID"); } |
However, if we do not set it, x is nil, and thus, our optional type
1 2 3 4 5 6 7 |
var x: Int?; if let tempX = x { print(tempX); } else { print("uh oh, x is NOT VALID"); } |
result:
uh oh, x is NOT VALID
Forced Unwrapping
Do forced unwrapping only if you are sure that the variable will not be nil.
1 2 3 4 5 6 |
var x: Int?; // declare OPTIONAL VARIABLE X! x = 45; // set optional variable //FORCED UNWRAPPING //x! (gives the Person value if it exists, runtime error if it is nil) print(x!); |
If x is valid, we’d get a valid int result. However, if x is not set, we’d get runtime error.
This language design forces the nil case to be handled explicitly, which improves safety over Obj-C
Classes/Structs and properties
A property declared with ‘var’ that belongs to a class is called a variable store property
A property declared with ‘let’ that belongs to a class is called a constant store property
1 2 3 4 5 6 7 8 9 |
class Accessor { //a stored property is a constant or variable that is stored //as part of an instance of a particular class or structure. public let title: String = "Mr" // constant variable store property public var name : String = "" // variable stored property } |
Stored Properties of Constant Structure Instances
If you create an instance of a structure and assign that instance to a constant, you cannot modify the instance’s properties, even if they were declared as variable properties:
1 2 3 4 5 6 7 8 9 10 |
// remember, struct is value type // All assignemnts are copied struct myStruct { public var description : String; init() { description = "NA"; } } |
Notice that myStruct contains variable store property, which means it is mutable. However, the instance of myStruct “s1” is constant. Thus, it is not possible to change “description”, even though it is a variable property.
1 2 |
let s1 = myStruct() s1.description = "This is a new Description" |
This behavior is due to structures being value types.
When an instance of a value type is marked as a constant, so are all of its properties.
The same is not true for classes, which are reference types.
If you assign an instance of a reference type to a constant, you can still change that instance’s variable properties.