Attributes and constants
If an instance with a struct is created and assigned a constant, no attributes of the instance can be modified:
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)rangeOfFourItems.firstValue = 6
- When an instance of the value type is declared as a constant, all its attributes become constants.
- When an instance of the reference type is assigned a constant, you can still modify the variable attributes of the instance.
Latency attribute
- Before the attribute declaration, use @ lazy to indicate a Delayed Storage attribute.
- The delayed storage attribute is the attribute that calculates the initial value when it is called for the first time.
- The delayed storage attribute must be declared as a variable (using the VaR keyword) because the attribute value may not be available until the instance construction is complete. The constant attribute must have an initial value before the construction process is complete, so it cannot be declared as a delay attribute.
-
When to use the latency attribute?
-
When the attribute value is dependent on external factors that cannot be known before the instance construction process ends
-
When the attribute value needs to be complex or computed in large quantities, it can be calculated only when needed.
Class datamanager {@ lazy var importer = dataimporter () var DATA = string [] () // This provides the data management function}Calculation attribute: getter and setter
If the setter of the calculation property does not define the parameter name that represents the new value, you can use the default name newvalue.
You must use the VaR keyword to define calculation attributes, including read-only calculation attributes, because their values are not fixed. The let keyword is only used to declare the constant attribute, indicating the value that cannot be modified after initialization.
Struct rect {VaR _ center: string; var center: String {get {return _ center;} set (newcenter) {_ center = newcenter }}// use newvaluestruct rect2 {VaR _ center: string; var center: String {get {return _ center ;} set {_ center = newvalue }}}Attribute Viewer
- The property observer monitors and responds to changes in attribute values. The attribute observer is called every time the attribute is set. Even when the new value is the same as the current value, the new value is no exception.
- You can add an attribute observer for other storage attributes except the Delayed Storage attribute,
- It does not need to be reloaded.Calculation attributeAdd an attribute observer because the setter can be used to directly monitor and respond to changes in the value.
- You can add an attribute observer for an inherited attribute (including storage and computing attributes) by reloading the attribute.
Attribute observer:
willSetCalled before setting a new value, the willset observer will pass in the new property value as a fixed parameter. In the implementation code of willset, you can specify a name for this parameter, if this parameter is not specified, the parameter is still available. newvalue is the default name.
didSetCall the new value immediately after it is set. The didset observer will pass in the old property value as a parameter. You can name this parameter or use the default parameter name oldvalue.
- Willset and didset will not be called during attribute initialization. They will only be called when attribute values are set outside of initialization.
struct Test{ var test:Int = 0{ willSet { println(newValue) } didSet{ println(oldValue) } }}var a = Test();a.test = 5;Global variables, local variables and latency attributes, calculation attributes, and attribute observer
Global or local variables are stored variables. They are similar to storage attributes. They provide a specific type of storage space and allow reading and writing.
- You can define computing variables in the global or local scope and define the observer for storage variables. Computing variables return a calculated value, like the computing attribute, instead of a stored value, and the declaration format is the same.
- Global constants or variables are computed with delay. They are similar to delayed storage properties. The difference is that global constants or variables do not need to be marked with the @ lazy feature. Constants or variables in the local range do not delay calculation.
var test:Int = 0{willSet { println(newValue)}didSet{ println(oldValue)}}test = 5 ;var str:String{get{ return String(test);}set {test = newValue.toInt()!+5}}println(str);str = "4";println(str)Type property --- Static Property
Use the keyword static to define the type attribute of the value type, and the keyword class to define the type attribute for the class:
Struct somestructure {static var storedtypeproperty = "some value. "Static Var computedtypeproperty: int {// here an int value is returned} Enum someenumeration {static var storedtypeproperty =" some value. "Static Var computedtypeproperty: int {// here an int value is returned} class someclass {class var computedtypeproperty: int {// here an int value is returned }}
The Type attribute is obtained and set through the type itself, rather than through the instance.
Println (someclass. computedtypeproperty) // output "42" println (somestructure. storedtypeproperty) // outputs "some value. "somestructure. storedtypeproperty = "another value. "println (somestructure. storedtypeproperty) // output "another value."
Self and parent
- Each instance of the type has an implicit attribute called self, which is equivalent to the instance itself.
- You do not have to write self frequently in your code. At any time, you only need to use a known attribute or method name in a method. If you do not explicitly write self, swift assumes that you are the attribute or method of the current instance.
- The main scenario of using this rule is that a parameter name of the instance method is the same as an attribute name of the instance. In this case, parameter names have priority and must be referenced in a more rigorous manner. In this case, you can use the self attribute to distinguish between parameter names and attribute names.
- The mutation method can assign a brand new instance to the hidden property self.
- In the method body of the type method, self points to the type itself, rather than a type instance. For struct and enumeration, this means you can use self to eliminate ambiguity between static attributes and static method parameters.
Struct point {var x = 0.0, y = 0.0 mutating func movebyx (deltax: Double, y deltay: Double) {self = point (X: x + deltax, Y: Y + deltay)} Enum tristateswitch {case off, low, high mutating func next () {Switch self {case off: Self = low case low: Self = high case high: self = off }}var ovenlight = tristateswitch. lowovenlight. next () // ovenlight is now equal. highovenlight. next () // ovenlight is now equal. offMutating
- Struct and enumeration are value types. Generally, the attribute of the value type cannot be modified in its instance method.
- To use the mutating method, put the keyword mutating before the func keyword of the method.
- You cannot call the mutation method on a struct type constant because the attributes of a constant cannot be changed, even if you want to change the attributes of a constant.
struct Point { var x = 0.0, y = 0.0 mutating func moveByX(deltaX: Double, y deltaY: Double) { x += deltaX y += deltaY }}var somePoint = Point(x: 1.0, y: 1.0)somePoint.moveByX(2.0, y: 3.0)Instance method
- The instance method can implicitly access all other instance methods and attributes of its type.
- An instance method can only be called by a specific instance of the class to which it belongs.
- The instance method cannot be called without the existing instance.
The method name in swift usually points to the first parameter of the method with a prefix, such as with, for, and.
External parameters of the method:
- By default, SWIFT only gives the first parameter name of the method a local parameter name. By default, it also gives the second and subsequent parameter names a local parameter name and an external parameter name.
- You can add an explicit external name or use a # As the prefix of the first parameter to use this local name as an external name.
- If you do not want to provide an external name for the second and subsequent parameters of the method, you can use the underscore (_) as the explicit external name of the parameter. This overwrites the default behavior.
class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes: Int) { count += amount * numberOfTimes }}let counter = Counter()counter.incrementBy(5, numberOfTimes: 3)Type method-Static Method
Declare the type method of the class, add the keyword class before the func keyword of the method, declare the struct and enumeration type method, and add the keyword static before the func keyword of the method.
struct LevelTracker { static var highestUnlockedLevel = 1 static func unlockLevel(level: Int) { if level > highestUnlockedLevel { highestUnlockedLevel = level } } static func levelIsUnlocked(level: Int) -> Bool { return level <= highestUnlockedLevel } var currentLevel = 1 mutating func advanceToLevel(level: Int) -> Bool { if LevelTracker.levelIsUnlocked(level) { currentLevel = level return true } else { return false } }}