Swift中類(Class)、結構(Struct)、列舉(Enum)差異

Una
彼得潘的 Swift iOS / Flutter App 開發教室
8 min readJul 20, 2023

在前幾次練習swift時,有請AI幫忙優化程式碼,其中在課堂上學習了class因此當下就用了class當方法寫了,但AI優化過後是使用struct,因此開始了解他們之間的差異。

來吧,Let’s go!

📍類(Class)

  • 類是一種引用類型(reference type)。當你創建一個類的實例時,實際上是在內存中分配一塊空間來存儲該實例,並將變量指向該內存地址。多個變量可以引用同一個類的實例,這意味著它們共享同樣的數據。
  • 類可以繼承自其他類,這允許你建立層次結構的類別。類的繼承可以重用父類的屬性和方法,並且還可以擴展和重寫它們。
  • 類支持釋放機制,允許使用者手動管理內存。當所有引用都被解除,內存才會被釋放。

🌟白話文:

1.類就像是一個模版,可以用來創建不同類型的東西。
2.想像成一個製造玩具的工廠,工廠就是類,而玩具就是類的實例。每個工廠生產不同種類的玩具,就像類可以創建不同類型的實例。
3.類的特點是可以有很多屬性和方法,讓我們可以在裡面存儲和處理很多資訊。

🌟用其他程式語言理解:

可以理解為javascript在new一個新的實例,當然概念上還是有些許不同。但可以先這樣理解。

// Swift
// 在Swift中的類(class)是一種定義自定義型別的機制,用於創建物件。
// 當你定義一個類時,實際上是定義了一個新的型別,可以用來創建該類的實例。
// 當你想要使用該類來創建實例時,需要使用初始化器(init)來進行實例化。
class Person {
var name: String
var age: Int

init(name: String, age: Int) {
self.name = name
self.age = age
}
}

// 使用類的初始化器來創建實例
let person = Person(name: "John", age: 30)
----------------------------------------------------------------
// JavaScript
// 在JavaScript中,new是用來創建物件的運算子。
// 當你有一個構造函數(constructor)時,使用new可以實例化一個新的物件。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
// 使用new來創建物件實例
const person = new Person("John", 30);
----------------------------------------------------------------
在JavaScript中的構造函數(constructor)是用constructor關鍵字定義的,
而在Swift中是使用init初始化器。

📍結構(Struct)

  • 結構是一種值類型(value type)。當你創建一個結構的實例時,實際上是在變量中存儲該實例的實際值,而不是引用。每個變量獨立存儲它們自己的數據,並且互不影響。
  • 結構不支持繼承,這意味著結構不能從其他結構或類繼承屬性和方法。然而,你可以實現協議(protocol)以達到類似的功能。
  • 結構在傳遞給函數或賦值給變量時是被複製的,這與類不同。這意味著當你修改一個結構的副本時,原始結構不會受到影響。

🌟白話文:

1.結構就像是一個小盒子,裡面可以放很多東西。
2.想像成一個魔法盒子,盒子裡面可以放不同種類的寶物,每個寶物是結構的一個實例。
3.結構的特點是每個實例都是獨立的,如果你改變了一個寶物,其他寶物不會受到影響。

🌟用其他程式語言理解:

可以理解為typescript的interface,當然概念上還是有不同。特別注意struct的值都是獨立的 ; interface只定義物件的結構,值會因為指向同個物件而互相影響。

// Swift
// Swift中的結構(struct)是一種值類型(value type),用於定義包含多個屬性的型別。
// 它可以像類(class)一樣有屬性和方法,但它是值類型,表示每個變數都包含自己的值,而不是指向同一個內存位置。
// 當你將一個結構賦值給另一個變數或傳遞給函數時,它們是相互獨立的,修改一個變數的值不會影響到另一個變數。
struct Point {
var x: Int
var y: Int
}

var pointA = Point(x: 5, y: 10)
var pointB = pointA // 複製pointA的值給pointB

print(pointA.x, pointA.y) // 輸出:5 10
print(pointB.x, pointB.y) // 輸出:5 10

pointA.x = 7
print(pointA.x, pointA.y) // 輸出:7 10
print(pointB.x, pointB.y) // 輸出:5 10
----------------------------------------------------------------
// TypeScript
// 在TypeScript(TS)中的介面(interface)用於定義物件的結構,它只描述物件的形狀,而不實際創建物件。
// TS的介面並不是一個真正的值類型,它只是一個規範或約定,用於確保物件擁有特定的屬性和方法。
interface Point {
x: number;
y: number;
}

let pointA: Point = { x: 5, y: 10 };
let pointB: Point = pointA; // 複製pointA的參考給pointB

console.log(pointA.x, pointA.y); // 輸出:5 10
console.log(pointB.x, pointB.y); // 輸出:5 10

pointA.x = 7;
console.log(pointA.x, pointA.y); // 輸出:7 10
console.log(pointB.x, pointB.y); // 輸出:7 10
----------------------------------------------------------------
Swift的結構還具有值類型的特性,而TypeScript的介面僅僅是一個規範,並沒有值本身。

📍列舉(Enum)

  • 列舉是一種特殊的值類型。它是一個定義了有限可能性的型別。每個可能的值稱為一個成員(member)。
  • 列舉的成員可以是關聯值(associated values),這使得列舉成員可以攜帶不同類型的相關數據。
  • 列舉也可以有方法,讓你對列舉進行操作和處理。

🌟白話文:

1.列舉就像是一個有限的選擇,你只能從中選擇其中一個。
2.想像成一個口袋裡有不同種類的糖果,你只能選擇一種吃。每種糖果就是列舉的一個成員。
3.列舉的特點是它只有特定的幾個選項,你不能自己隨意添加。

🌟使用場景:

enum Direction {
case up
case down
case left
case right
}

// 創建一個Direction列舉的實例
let playerDirection = Direction.up

switch playerDirection {
case .up:
print("Player is moving up")
case .down:
print("Player is moving down")
case .left:
print("Player is moving left")
case .right:
print("Player is moving right")
}
// 輸出:Player is moving up

整理過後

類(Class):

  • 類就像是一個大家庭,裡面有很成員住在一起。每個成員都有自己的名字和年齡,還可以做各種各樣的事情。
  • 你可以讓這個大家庭裡的每個人都知道同樣的事情,也可以讓他們一起做一些有趣的活動。

結構(Struct):

  • 結構就像是一個小房子,裡面只有一個人住。這個人有自己的名字和年齡,也可以做各種各樣的事情。
  • 這個小房子裡的這個人可以做自己喜歡的事情,不用理會別的房子的人。

總結:

  • 類就像是一個大家庭,裡面有很多人住在一起,他們可以一起做事情並分享資訊。
  • 結構就像是一個小房子,裡面只有一個人住,他可以獨立做自己的事情,不用理會其他房子的人。
  • 因為Class的Copy by Reference,因此不同的thread有可能同時在修改此物件中的變數,而使用struct就不必擔心會有此問題的出現。

參考:

https://ithelp.ithome.com.tw/articles/10200859

--

--