Swiftを勉強してて、おそらく誰もがこう思うはず、、、『ClassとStructの違いってなんや…一緒やんけ😨』
なんならenumもなんやねんって思ってます(ふふふ
でもそんな僕でも今回ざっくりと理解出来たので書いちゃいます😎
Swift v.5.1.3でやります
1番の違い
まずClassとStructの1番の違いは、Classは参照、Structはコピーです。
もっと噛み砕いた言い方をすると、Classは原本です。
例えば10人程のメンバーが集まって会議をするとしましょう、Classを使って会議をする場合は原本しか使えないので、1つの用紙を使って10人の意見や結果内容を書いていきます。
原本なので上書き保存の繰り返し、、、当然中身は無茶苦茶になり大炎上です🔥😱(oh!
そんな時に役立つのがStructです!Structはコピーなので10人分の用紙を用意して意見を交わし合えます!これで炎上を避けて会議が出来ます😊(やったぜ
パン屋の経営に置き換えてコードで実践してみましょう🍞
とある町にパン屋がありました、このパン屋さんはクロワッサンと食パンを売っていて、とても美味しいと評判でいつも大賑わいです👩🍳{忙しい
class ClassBakery {
// クロワッサン
var croissant: Int
// 食パン
var plainBread: Int
init(croissant: Int, plainBread: Int) {
self.croissant = croissant
self.plainBread = plainBread
}
}
var price = ClassBakery(croissant: 200, plainBread: 300)
// クロワッサン200円
print("クロワッサン\(price.croissant)円")
// 食パン300円
print("食パン\(price.plainBread)円")
そんなパン屋さんが努力の甲斐があり、ついに2号店をオープンする事になりました!新店舗オープン価格で2号店のみ半額で販売します!
// 1号店
var price = ClassBakery(croissant: 200, plainBread: 300)
// 2号店
var newBakeryPrice = price
// 2号店は半額に設定
newBakeryPrice.croissant = 100
newBakeryPrice.plainBread = 150
// クロワッサン200円?
print("1号店 クロワッサン\(price.croissant)円")
// 食パン300円?
print("1号店 食パン\(price.plainBread)円")
// クロワッサン100円?
print("2号店 クロワッサン\(newBakeryPrice.croissant)円")
// 食パン150円?
print("2号店 食パン\(newBakeryPrice.plainBread)円")
これで1号店は通常価格、2号店は半額セールで販売ができるはずです!早速販売しましょう!🤑
ってあれ!? 1号店も半額になってしまっています!!😱
これはマズい!!このままだと大赤字になってしまいます!2号店の価格が1号店にも反映されてしまっているのでしょう、急いで価格を修正します😰
でも当然ながらそんな事したら2号店の価格が半額になりません!!!😱
お客さんは半額になってないじゃないかと大激怒!🤬Twitterで詐欺パン屋と拡散されてしまい大炎上🔥🔥🔥
もう破産待った無しです。。。😇
Sturctを使おう!
悲しい事件でしたね😭今回の敗因はClassを使って価格の設定をしてしまっている事です。Classは原本なので、途中で価格を変更すると紐づいてる全てのデータが変わってしまいます。ゲーム風に言うと上書き保存です!
なので、このパン屋が生き残る世界線を作るにはStructを使います!早速やっていきましょう!
Structの場合はClassと違ってinitを書く必要がありません!内部で自動的にやってくれます!
struct StructBakery {
// クロワッサン
var croissant: Int
// 食パン
var plainBread: Int
}
そしてさっきのコードをClassBakeryからStructBakeryに変更します!
// 1号店 👇ここをStructBakeryにする
var price = StructBakery(croissant: 200, plainBread: 300)
// 2号店
var newBakeryPrice = price
// 2号店は半額に設定
newBakeryPrice.croissant = 100
newBakeryPrice.plainBread = 150
// クロワッサン200円?
print("1号店 クロワッサン\(price.croissant)円")
// 食パン300円?
print("1号店 食パン\(price.plainBread)円")
// クロワッサン100円?
print("2号店 クロワッサン\(newBakeryPrice.croissant)円")
// 食パン150円?
print("2号店 食パン\(newBakeryPrice.plainBread)円")
これで準備完了です!販売してみましょう、結果は、、、👩🍳{ドキドキ
おめでとうございます!無事に1号店は通常価格、2号店は半額で販売できました!!😆🎉
これでお客さんは怒ることもなく、Twitterも炎上せずに破産せずに済みます!👩🍳{よかった、よかった
これが実現できたのはStructがコピーだからです。1号店からデータを参照しているのではなく、データをコピーしているので、2号店で価格を変更しても1号店に影響は起きなかったのです!
こんな感じ👇
// 1号店
var price = StructBakery(croissant: 200, plainBread: 300)
// 2号店
var newBakeryPrice = price 👈ここでコピー
// 2号店は半額に設定
newBakeryPrice.croissant = 100 👈コピーしたデータを変更
newBakeryPrice.plainBread = 150 👈コピーしたデータを変更
// クロワッサン200円?
print("1号店 クロワッサン\(price.croissant)円") 👈元のデータが反映される
// 食パン300円?
print("1号店 食パン\(price.plainBread)円") 👈元のデータが反映される
// クロワッサン100円?
print("2号店 クロワッサン\(newBakeryPrice.croissant)円") 👈コピーして変更したデータが反映される
// 食パン150円?
print("2号店 食パン\(newBakeryPrice.plainBread)円") 👈コピーして変更したデータが反映される
なのでClassにはSuperClassといってクラスを継承し、親クラスを作ることが出来ますが、Structはコピーなので親を作って継承することが出来ません。(コピーだから親も糞もない)
終わり
以上がClassとStructの1番の違いでした!ざっくりとですが理解出来ましたでしょうか?
ClassとStructの違いは他にもデータの保存場所の違いなど、いろいろあるのですが、そこら辺はまだしっかり理解出来ていないので、もっと知識が固まったら細かい違いなども別記事で書いていきたいと思います!
それでは
👩🍳{ See you