[Swift] Type component ~ Property Part 2 ~

This article is a continuation of [Swift] type component ~ Property Part 1 ~. If you have a lot of things you don't understand even after reading this article, please see the first part.

Now, let's continue from the first part.

Stored properties

The properties are ** stored properties that hold values ​​** and It can also be categorized into two types: ** Compute properties that do not hold values ​​**.

One thing to note is ** Because both stored and compute properties are categorized by whether they hold values It can be an instance property or a static property. ** **

First, let's talk about stored properties.

Stored properties, like variables and constants, are properties that assign and store values. As a definition method, use the var keyword and let keyword as well as variables and constants.


var instance property name:Property type=formula
let instance property name:Property type=formula
static var instance property name:Property type=formula
static let instance property name:Property type=formula

It's a property that holds a value, so you can write it as above!

The actual code looks like this.


struct Sample {
    var sampleA = 123
    let sampleB = 456
    static var staticSampleA = 789
    static let staticSampleB = 890
}

let sample = Sample()
sample.sampleA   // 123
sample.sampleB   // 456
Sample.staticSampleA   // 789
Sample.staticSampleB   // 890

Property observer

Property observers * * monitor changes in stored property values ​​and It executes the statement before and after the change. ** **

To define, add {} to the end of the stored property definition. Use the ** willSet keyword ** to describe the statement to be executed before the change. The statement to be executed after the change is specified by the ** didSet keyword **.


var property name=initial value{
   willSet {
Statement executed before changing properties
The changed value is"newValue"Can be accessed as
   } 
   
   didSet {
Statement executed after changing properties
   }
}

As the name suggests, stored properties are not updated at the time of willSet. Instead, you can access the new value with newValue.

I wrote the following code.

If the value of the name property changes print ("change name \ (name)-> \ (newValue) ") prints the current and new values.

After that, didSet outputs the new current value.


struct Sample {
    var name = "Saitou" {
        willSet {
            print("change name \(name) -> \(newValue)")
        }
        didSet {
            print("now name value is \(name)")
        }
    }
}

var sample = Sample()
sample.name = "Takada"

Execution result
change name Saitou -> Takada
now name value is Takada

Lazy stored properties

Lazy stored properties are properties that delay initialization until they are accessed. Define by adding the lazy keyword before the property.


lazy var instance property name:Property type=formula
static lazy var Static property name: Property type=formula

As you can see from the code above, ** cannot be used with non-reassignable properties. ** **

Let's actually check the initialization timing.

As a method, describe the property with the print () function at the time of initialization, Access the properties in order.


struct Sample {
    var value: Int = {
        print("Generates a value for value.")
        return 1
    }()
    
    lazy var lazyValue: Int = {
        print("Generates a value for lazyValue.")
        return 2
    }()
}

var sample = Sample()
print("I instantiated the Sample.")
print("The value of value is\(sample.value)is.")
print("The value of lazyValue is\(sample.lazyValue)is.")

Execution result
Generates a value for value.
I instantiated the Sample.
The value of value is 1.
Generates a value for lazyValue.
The value of lazyValue is 2.

** From the execution result, normal properties are initialized at instantiation, You can see that the lazy stored property is initialized at the time of access. ** **

Actually, this delayed initialization is quite convenient, ** Deferred costly property initialization to access time, You can improve the performance of your application, **

Also, usually when initializing stored properties, Other properties and methods are not available.

However, lazy stored properties are initialized after instantiation, so ** You can access other properties and instances during initialization. ** **

In the part of lazy var lazyValue = double (of: 10) The double (of :) method is used to initialize lazyValue.

The double (of :) method is a method that doubles the value of the argument.

Since we are passing a value of var value = 10 as an argument, 20 is returned.


struct Sample {
    var value = 10
    lazy var lazyValue = double(of: 10)
    
    func double(of value: Int) -> Int {
        value * 2
    }
}

var sample = Sample()
sample.lazyValue   // 20

Computed properties

Compute properties do not store values ​​on their own, ** A property that returns a value calculated from an existing stored property. ** **

The advantage of computeed properties is that they recalculate the value for each access. The point is that it is always consistent with the value from which it was calculated.

For compute properties, specify the property name and type name after the var keyword. In ** {}, define the getter with the get keyword and the setter with the set keyword. ** **

Getter is a process that returns properties, The setter is the process of updating the value of a property.


var property name:Model name{
   get {
Returns a value by the return minute
   }
  
   set {
Update value
The value assigned to the property can be accessed with newValue
   }
}

Getter

Getters get values ​​from other stored properties etc. It is a process that returns as the value of the compute property. Use the return statement to return the value.

An example of a getter is as follows.

The value property returns the value of the stored property count in the getter. So if you access a compute property value that doesn't hold a value, you'll get 10.

Also, if you access value after substituting +10 for count with sample.count += 10, The latest value value is returned.

** In this way, getter's strength is that consistency is always maintained. ** **


struct Sample {
    var count = 10
    var value: Int {
        get {
            return count
        }
    }
}

var sample = Sample()
sample.value   // 10
sample.count += 10
sample.value   // 20

** You can omit the setter in the Computed Properties, but you cannot omit the getter. ** ** If the setter is omitted, the get keyword and {} can be omitted.

However, if you omit the get keyword, you will not be able to see it at all. Personally, I think it's better to write it to improve readability ... (Is it okay if I get used to it?)

By the way, when I try to assign a value to a ** getter, I get a compile error. ** **


struct Sample {
    var value: Int {
        return 10
    }
}

var sample = Sample()
sample.value = 10   //Compile error

Error details: Cannot assign to property:'value' is a get-only property Japanese translation: Cannot be assigned to a property:'value' is a get-only property

Setta

The setter uses the value assigned to the property, It is a process to update other stored properties.

Within the setter, ** through an implicitly declared constant called newValue It is possible to access the assigned value. ** **

You can use this value to change the value of other properties.

Some of the vending machine functions have been coded below.

As stated in var money = 0, the initial total amount is 0 yen. When you put in money, the total amount will be added by money + = new Value in the setter.

Get the value of money by performing getter processing with sample.money.


struct Sample {
    var money = 0
    
    var addMoney: Int {
        get {
            return money
        }
        set {
            money += newValue
        }
    }
}

var sample = Sample()
sample.money   // 0
sample.addMoney = 100
sample.money   // 100
sample.addMoney = 50
sample.money   // 150

Next is how to use the setter, which is a little more difficult.

By defining a setter with set (value) {} ** You can treat the assigned value as value instead of newValue. ** **

That is, instead of the newValue implicitly declared by adding the name inside the () of set () You can use a constant with any name you like.

Also, since it is not always necessary to put a value in another property in the setter, The value to be assigned by switch value {} and the value not to be assigned are sorted.


struct Sample {
    var money = 0
    
    var addMoney: Int {
        get {
            return money
        }
        set(value) {
            switch value {
            case 1, 5, 5000, 10000:
                print("\(value)Yen cannot be used")
            case 10, 50, 100, 500, 1000:
                print("\(value)I put a yen.")
                money += value
                print("The current total amount is\(money)It is a circle.")
            default:
                print("This money cannot be used at vending machines.")
            }
        }
    }
}

var sample = Sample()
sample.addMoney = 10000
sample.addMoney = 500
sample.money   // 500

Execution result
10,000 yen cannot be used
I put in 500 yen.
The current total amount is 500 yen.

The above is the explanation of the property.

** I think that setters and getters will improve the integrity of the program and improve safety. Please remember and use it! ** **

Please see another article for more details on the components of the type!

-[Swift] Type component-Type basics- -[Swift] type component ~ method ~ -[Swift] type component ~ initializer ~ -[Swift] type component ~ subscript ~ -[Swift] type component ~ extension ~ -[Swift] type component ~ type nesting ~

Thank you for watching until the end.

Recommended Posts

[Swift] Type component ~ Property Part 2 ~
[Swift] Type component ~ Initializer ~
[Swift] Type component ~ Method ~
[Swift] Type type-Class first part-
[Swift] Type type ~ Enumeration type ~
[Swift] Type type ~ Structure ~
[Swift] Type components ~ Type nesting ~
[Swift] Type design guidelines
[Swift] Shared enumeration type
[Swift] Type type-Class sequel-
[Swift] Summary about Bool type
Great Swift pointer type commentary
Introduction to swift practice output Type representing the Chapter 4 collection Part 1
Introduction to swift practice output Type representing the Chapter 4 collection Part 2
[Swift] Property observers willSet and didSet