はじめに
Qiita初投稿になります。2018年1月からプログラミングの学習を開始し、今までPython, Swift, Rubyを触ってきました。エンジニアとしてスキルアップしていくためにも、各言語の仕様を理解したコードがかけるようになりたいと考えていますのでアドバイス等いただけると嬉しいです。
この記事の目的・背景
今までプライベートiOSアプリを開発していたが、Class以外にStructやEnumを積極的に使ってこなかったのでclass、struct、enumの比較とそれぞれどのような場面で使用できるかまとめてみます。今回はClassとStructの比較を主に書いてみます。
ClassとStructの大きな違い
まず始めに、SwiftのClassとStructの大きな違いをおさらいしてみます。
・Classは継承可能だが、Structはできない
・Classインスタンスは参照型、Structは値型
var someValue1 = SomeValue(value:20)
var someValue2 = someValue1
someValue2.setNewValue(value:21)
// Class (someValue1, someValue2どちらも変わる)
// someValue1.value = 21
// someValue2.value = 21
// Struct (someValue1の値は変化しない)
// someValue1.value = 20
// someValue2.value = 21
letによるMutabilityが異なる
class Something {
var mutableValue = 10
}
let immutableClass = Something()
// Cannot assign to value: 'immutableClass' is a 'let' constant エラー
// immutableClass = Something()
immutableClass.mutableValue = 20
// immutableClass.mutableValue => 20
struct SomeStructure {
var immutableValue = 10
}
let immutableStruct = SomeStructure()
// immutableStruct = SomeStructure()
// Cannot assign to value: 'immutableClass' is a 'let' constant エラー
// immutableStruct.immutableValue = 20
// Cannot assign to property: 'immutableStruct' is a 'let' constant エラー
let
で定義すると、 Classのインスタンスはimmutableになりますが、プロパティはmutableのままになっています。一方、Structはデータをカプセル化して保持する役割がありますので、そのまま外部から値を変更しようとするとエラーになります。
Struct内で定義したプロパティの値を変更するには、メソッドの前に mutating
をつける
Struct内のプロパティの値を変更する際は、mutating
をメソッドの先頭につけることでプロパティの値を変更することが可能になります。
struct SomeStructure {
var value:Int
init(value:Int) {
self.value = value
}
mutating func addOne(){
self.value += 1
}
// 下記のように、mutatingをつけないと、Left side of mutating operator isn't mutable: 'self' is immutable というえらエラーが発生する
// func addTwo(){
// self.value += 2
// }
}
var something = SomeStructure(value: 1)
something.addOne()
// something.value => 2
Structを使うメリット
- クラスのように簡単に使える
- クラスファイルが増えすぎない
- データ自体に関する処理を任せることで構造がわかりやすくなる
・クラスのように簡単に使える
クラスを定義するときと同様にイニシャライザも使え、プロパティやメソッドの定義も簡単!
・クラスファイルが増えすぎない
クラス毎にファイルを分ける必要がなくなり、データに関する処理をStructファイルでまとめてしまったり、Controllerファイルに記載しても良いので他のクラスファイルと分離して管理することができます。
・データ自体に関する処理を任せることで構造がわかりやすくなる
図の様にコントローラーファイル、モデルファイル、Structファイルを用意し、それぞれ適切な役割(例えばStructに全てデータに関する変数と処理を書く)を与えることでコードの可読性が上がり、チームで開発する際に新規メンバーのキャッチアップも早くなりそうです。
まとめ
Structはクラスの様に書くことができ、データを保持し、データの処理を行う関数をまとめるのに適しています。しかしながら、継承が存在せず、Struct単体では不便な点もあります。サブクラスのようなものを作成したい時には、Enumも同時に利用することで同様の機能を実装可能ですので、次回はEnumも利用したコードの可読性をあげる方法を考えてみようと思います。
最後まで読んでいただき、ありがとうございました!不明な点や間違いがありましたらコメントしていただけると嬉しいです〜!