Examples of SWIFT classes and structures that behave differently when changing properties

Asked 2 years ago, Updated 2 years ago, 118 views

I'm studying swift, but I don't know much about classes and structures.

When function a calls function b, if the instance of the class is passed to function b as an argument, changing the value of the class property in function b also changes the property of the class in function a, and
When function a calls function b, if you give an instance of a structure to function b as an argument, changing the value of the property of the structure in function b will not change the property of the structure in function a. Could you give me a specific example?

If possible, I'd like a program that even beginners can understand.

This is swift 4.x.

swift swift4

2022-09-30 19:38

3 Answers

Both of you have already answered, but both emphasize that "If you declare a value type variable with let, its member cannot be changed." For example, changing the property of a value type copy does not change the original property.

First, simply define the structure and class.

structure MyStruct{
    var prop: String = "initial"
}

US>class MyClass {
    var prop: String = "initial"
}

First, if function a calls function b and gives an instance of a structure to function b as an argument, changing the value of the property of the structure in function b does not change the property of the structure in function a.

*If you run these codes on Playground, you will get a lot of warnings, but please ignore them as they are for experimentation now.

funca1(){
    varstructInstance=MyStruct()
    print(structInstance.prop)//->initial
    b1(structInstance)
    print(structInstance.prop)//->initial
}

funcb1(_argInstance:MyStruct){
    varvarInstance=argInstance//As properties cannot be changed as they are, substitute `var` variable
    varInstance.prop = "changed"
}

When you call a1() in this state, initial appears twice as the comment states.I have definitely changed the value of the property prop of the varInstance in the function b1, but it is not reflected in the original structureInstance.

It may appear to be because of a line like varvarInstance=argInstance, but writing exactly the same way in a class does not work."If you pass an instance of a class to function b as an argument, changing the value of the class property in function b also changes the property of the class in function a."

funca2(){
    varclassInstance=MyClass()
    print(classInstance.prop)//->initial
    b2(classInstance)
    print(classInstance.prop)//->changed
}

funcb2(_argInstance:MyClass) {
    varvarInstance=argInstance//You can change the properties as they are, but keep them exactly the same code as in the structure
    varInstance.prop = "changed"
}

Running a2() in this state rewrites the varInstance property and certainly rewrites the classInstance property.

I think the difference is obvious when I actually move it, but I will explain a little more.

For value-type variables such as structures, each variable (conceptually) has a copy of the value, just before running varInstance.prop="changed" in b1().

a1's structureInstance+-----------------------------------+
                    |MyStruct|
                    +----+------------------+
                    | prop | "initial" |
                    +----+------------------+

argInstance+ -------------------------------------------------------
                    |MyStruct|
                    +----+------------------+
                    | prop | "initial" |
                    +----+------------------+

varInstance+ ---------------------------------------------------------
                    |MyStruct|
                    +----+------------------+
                    | prop | "initial" |
                    +----+------------------+

If you run varInstance.prop="changed" here, you'll see that.

a1's structureInstance+-----------------------------------+
                    |MyStruct|
                    +----+------------------+
                    | prop | "initial" |
                    +----+------------------+

argInstance+ -------------------------------------------------------
                    |MyStruct|
                    +----+------------------+
                    | prop | "initial" |
                    +----+------------------+

varInstance+ ---------------------------------------------------------
                    |MyStruct|
                    +----+------------------+
                    | prop | "changed" |
                    +----+------------------+

On the other hand, for a reference class instance, the body is in a different place from the variable, and only the "reference" to the body is in the variable.b2() before varInstance.prop="changed" is executed.

The unit is in a different location (called heap) and will not be copied.
classInstance+----------------------------------------------------------------------------
                    |  [ ] ------=== > | MyClass |           
                    +------+    /  /  +----+------------------+
                               /  / | prop | "initial" |
                              /  /    +----+------------------+
b2 argInstance+--------+/
                    |  [ ] --- / / The reference has been copied, so everyone points to the same location
                    +------+  /
                             /
varInstance +----------+/ on b2
                    |  []---/
                    +------+

This is what happens when varInstance.prop="changed" runs here, and in the case of reference type, the property change follows the reference and changes the properties of the body.

a2 classInstance+-------------------------------------------+
                    |  [ ] ------=== > | MyClass |           
                    +------+    /  /  +----+------------------+
                               /  / | prop | "changed" |
                              /  /    +----+------------------+
b2 argInstance+--------+/
                    |  [ ] --- / / The reference has been copied, so everyone points to the same location
                    +------+  / In other words, everyone is pointing to the changed body.
                             /
varInstance +----------+/ on b2
                    |  []---/
                    +------+

"For value-type variables, each variable has a copy of the value" above is conceptual, and although optimization actually prevents copying as much as possible (because copying large structures is difficult), meaning the same result as saying "each variable has a copy of the value."


2022-09-30 19:38

Does the questioner understand the difference between declaring variables in let and var?
When you declare with let, variables declared with let become constants and cannot be changed (compilation errors).
 This is the same for structures, and even if you declare a member of a structure with var, if you declare a variable of structure type with let, the member of the structure can only be changed at initialization.

So far, the following is a sample.
If you paste it into the playground, you will encounter three compilation errors.
I have commented on the part where the error occurs, so please read it.

structureBookStruct{
    variable —String
    var author —String
}// end define structure BookStruct

classBookClass{
    variable —String
    var author —String

    init(title: String, author: String) {
        self.title=title
        self.author = author
    }// end init
}// end define class BookClass

func createBook(title: String, author: String) {
    varbook1 = BookStruct (title: title, author: author)
    book1.title="def"// OK
    letbook1b = BookStruct (title: title, author: author)
    Book1b.title="def" //let declared, but I am trying to change the contents, so I will not allowed.
    modifyTitle(book:book1, newTitle: "abc") // Comment:moffifyTitle in bookStruct1 is called
    modifyTitle(book:&book1,newTitle:"abc") // comment bookStruct2 modifyTitle is called

    letbook2 = BookClass (title: title, author: author)
    book2.title="def" // OK
    modifyTitle(book:book2, newTitle: "def") // comment bookClass modifyTitle is called

}

// bookStruct1
func modifyTitle(book:BookStruct, newTitle:String) {
    The book.title=newTitle//book is passed the value copied in let, so if you try to change it, it will not work.
}

// bookStruct2
func modifyTitle(book:inoutBookStruct, newTitle:String) {
    Book.title=newTitle//book received a reference to the value in the inout declaration, so OK.
}

// bookClass
func modifyTitle(book:BookClass, newTitle: String) {
    book.title=newTitle//book itself is a value-delivering, but it is an instance of the class, so you can change the properties.
    book=BookClass(title: "cde", author: "aaa") // Trying to rewrite the book itself is not allowed
}


2022-09-30 19:38

In your question,

When function a calls function b, if the class instance is passed to function b as an argument,

Examples of include:

class User {
    var name = "taro"
}

func function a(){
    var user = User()
    Function b(user)
    print(user.name)//=>"hanako"
}

func function b(_user:User){
    user.name="hanako"
}

Function a()

Also,

If you pass an instance of a structure as an argument to function b

The specific example in is a user change from class to structure, which results in a compilation error in function b.

(Because the values crossed by the argument are treated as defined by let, and the structure cannot change the properties of the instance defined by let.)

Therefore,

in your question

Changing the value of the property of a structure in function b does not change the property of a structure in function a

is not a valid

The value of a structure property in function b cannot be changed directly (by default)

I think so.


2022-09-30 19:38

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.