Swiftにおけるクラスと構造体の違いとその使い分け – 参照渡しと値渡し

Swiftはオブジェクト指向に基づいたプロトコル指向型言語である。オブジェクト指向型言語によるプログラミングは、クラス(class)というオブジェクトの設計図を定義することから始まる。Swiftではクラスによく似た構造体(struct)というオブジェクトを持つことができる。クラスと構造体の大きな違いは

  1. クラスは参照型のデータである一方、構造体は値型のデータである。
  2. クラスは継承できるが、構造体は継承できない。

の2点である。継承できるか否かという違いは、単にスーパークラス(親クラス)を設定できるか否かということで容易に理解できるが、参照型(参照渡し)か値型(値渡し)かという差異は直感的に理解しづらい。そこで今回、参照渡しか値渡しかという点に着目し、クラスと構造体の違いについて紹介する。

クラス(class)は参照渡し

Swfitにおけるクラスのインスタンスは参照型であり、インスタンスを変数に代入等された場合、そのコピーが作られるのではなく、同一のインスタンスへの参照が渡される(C言語に馴染みのある方はポインタをイメージすると容易に理解できるでしょう)。その例は以下の通りである。

// MARK: Class - 参照渡し

class MyClass {
    var a: Int = 1
}

let myClassA = MyClass() // MyClassをインスタンス化
var myClassB = myClassA // myClassAのインスタンスの参照をmyClassBに代入
myClassB.a = 2

print("myClassA.a: \(myClassA.a), myClassB.a: \(myClassB.a)")
// myClassA.a: 2, myClassB.a: 2

ここではmyClassAMyClassクラスをインスタンス化したものを代入する。そしてmyClassBmyClassAを代入している。これは myClassAのインスタンスの参照をmyClassBに代入する ことになり、 myClassAmyClassBは同様のMyClassインスタンスを参照している ことになる。したがってmyClassB.a2を代入した場合、参照元のインスタンスが同じためmyClassA.a2となる。

構造体(struct)は値渡し

一方、構造体は、クラスとは異なり値渡しとなる。代入や関数呼び出しの際、データの参照ではなく実態がコピーされ、新しいインスタンスが渡される。その例は以下の通りである。

// MARK: Struct - 値渡し

struct MyStruct {
    var a: Int = 1
}

let myStructA = MyStruct() // MyStructをインスタンス化
var myStructB = myStructA // myStructAのインスタンスをmyStructBにコピー
myStructB.a = 2

print("myStructA.a: \(myStructA.a), myStructB.a: \(myStructB.a)")
// myStructA.a: 1, myStructB.a: 2

myStructAにはMyStruct構造体のインスタンスを代入し、そのmyStructAmyStructBに代入している。先ほどのクラスの例では、myStructAmyStructBの参照するインスタンスが同じとなるが、構造体の場合はmyStructBmyStructAに代入されているインスタンスを複製することになり、結果、別のインスタンスを参照することになる。したがってmyStructB.a2を代入したとしても、参照元のインスタンスが異なるためmyStructA.aは初期値の1である。

クラス(class)と構造体(struct)の使い分け

以上の参照渡しと値渡しの違いから、実際のコーディングによるクラスと構造体の使い分けは、以下の通りと考えられる。

  1. 複数個所から同じインスタンスを参照し、インスタンスのプロパティなどを動的に結びつけたい場合はクラスを使う。
  2. 構造や挙動が静的に定められており、特に所定のプロパティを複数個所から参照する必要のない場合は構造体を使う。

クラスと構造体の選択を迷う前に、クラスを使うプログラマーも多く、ほとんどの場合はそれで特に問題も起こらない。だがそんな中でも 小さくて単純なデータをカプセル化する場合や、単純な処理の集合体などを記述する場合は構造体 を採用すれば、コード内のオブジェクトにこれまで以上に意味を持たせることができ、可読性の高いプログラムが書くことができるだろう。

雑感

今回、結構がっつりと真面目に記事を書いたつもりですw よって以前の記事とは違って、自然と論文口調となりましたw ←やっぱり実際これが一番僕は執筆しやすい

参照渡しか値渡しかは実際にプログラミングしてみないと実感できないと思います(自分はそうでした)。どういった場面で使い分けるのかも含めて。今後のコーディングではこの使い分けを意識していこうと思いました。本記事が少しでも皆様の理解の助けとなることを祈っております。

以上、たまには真面目に寄稿した博士でした(`・ω・´)ゞ

参考

本記事のサンプルコードは下記記事を参考によりシンプルに書き換えたものです。

Swift class と struct の違い/使い分け

Swift3版でましたね!Swiftの言語仕様を理解するには一番いい。

コメントを残す

メールアドレスが公開されることはありません。