74456


# 質問

クラスでは参照渡し、構造体では値渡しということ風に学んだので、実際に試してみたのですが、メソッドにmutatingをつけてしまえば同じなのでしょうか？構造体にmutatingをつけないとエラーが出てself(プロパティ)を変更できないと出てしまいます。

## クラス

[code]

    class Dog {
        var name: String = "Dog"
    
        func methodA() {
            print(self.name)
        }
       func methodB() {
            self.name = "Cat"
            print(self.name)
        }
    
    }
    
    var dog = Dog()
    
    dog.methodA() //期待[Dog],実際[Dog]
    dog.methodB() //期待[Cat],実際[Cat]
    dog.methodA() //期待[Cat],実際[Cat]
    
[/code]

## 構造体

[code]

    struct Dog {
        var name: String = "Dog"
    
        func methodA() {
            print(self.name)
        }
        mutating func methodB() { //mutatingがないとエラーになる
            self.name = "Cat"
            print(self.name)
        }
    
    }
    
    var dog = Dog()
    
    dog.methodA() //期待[Dog],実際[Dog]
    dog.methodB() //期待[Cat],実際[Cat]
    dog.methodA() //期待[Dog],実際[Cat] //値渡しのはず？なのでDogであってほしい
    
[/code]


CC BY-SA 4.0
2021-03-06T07:07:31.503
74455
2021-03-06T08:58:00.100
40856
question
swift
Swiftのクラスと構造体について


> クラスでは参照渡し、構造体では値渡しということ風に学んだ

(最初に詳細な言葉遣いの問題について突っ込むのもなんですが、これを間違えたままでいると、今後プログラミング言語の学習に支障をきたすことになるので。)

「参照渡し」「値渡し」と言う言葉は、関数呼び出しの際にパラメータがどのように渡されるのか表す用語であり、ご質問のような文脈で使うのは不適切です。

Swiftでは、「クラスは参照型、構造体は値型」と言うのが正しい言い方になります。  
(ちなみにSwiftでは、「値渡し」はあっても「参照渡し」はありません。`inout`渡しなんてあまり他言語にはない特殊なものがありますが、「参照渡し」とは異なります。)

残念ながら、ネット上の検索結果で上位にくる記事の中にも同じ間違いがかなり見つけるので注意してください。

* * *

「参照型」「値型」の違いをできるだけ簡単に表すと、「本体は別の場所にあって、変数はその場所の住所を保持する」のが「参照型」、「全ての変数が本体のコピーを保持する」のが「値型」になります。

従って、あなたが作られた例では変数が1個しか登場しないので、参照型と値型の違いは見つけにくいでしょう。  
2個以上の変数を使う例を作ると、違いが見つけやすくなります。

### 「参照型」の例

[code]

        class Dog {
            var name: String = "Dog"
            
            func methodA() {
                print(self.name)
            }
            
            func methodB() {
                self.name = "Cat"
                print(self.name)
            }
        }
        
        var dog1 = Dog()
        dog1.methodA()
        var dog2 = dog1
        print(dog1.name, dog2.name) //->Dog Dog
        dog1.methodB()
        print(dog1.name, dog2.name) //->Cat Cat
    
[/code]

### 「値型」の例

[code]

        struct Dog {
            var name: String = "Dog"
            
            func methodA() {
                print(self.name)
            }
            
            mutating func methodB() {
                self.name = "Cat"
                print(self.name)
            }
        }
        
        var dog1 = Dog()
        dog1.methodA() //->Dog
        var dog2 = dog1
        print(dog1.name, dog2.name) //->Dog Dog
        dog1.methodB() //->Cat
        print(dog1.name, dog2.name) //->Cat Dog
    
[/code]


CC BY-SA 4.0
2021-03-06T08:58:00.100
74456
2021-03-06T08:58:00.100
13972
74455
answer