類別是物件導向很重要的一個概念,在開發遊戲時也常用到它。
可以把它想像成一張角色設計圖,裡頭可能定義了角色會具備的屬性、能力。有了這張設計圖後,我們可以製作角色出來,也就是將角色實體化,變成一個真實的角色物件 (object)。
Role
,具有頭髮顏色 hairColor
跟眼睛顏色 eyeColor
兩種屬性init
,可帶入參數,並且在初始化時賦予 hairColor
及 eyeColor
值run
、跳 jump
class Role {
var hairColor: String
var eyeColor: String
init(hairColor: String, eyeColor: String) {
self.hairColor = hairColor
self.eyeColor = eyeColor
}
func run() {
print("run")
}
func jump() {
print("jump")
}
}
Role(hairColor: "orange", eyeColor: "blue")
可以創建一個實體,並且帶入這個角色特有的參數。例如我們創建一個人類的角色實體 human
human.hairColor
取得實體的屬性human.run()
可以執行方法let human = Role(hairColor: "black", eyeColor: "brown")
print("hair color: \(human.hairColor)")
print("eye color: \(human.eyeColor)")
human.run()
human.jump()
印出結果:
hair color: black
eye color: brown
run
jump
提到類別就不能少了繼承的概念,當一個 A 類別繼承了 B類別,則 B類別稱為父類別,A類別稱為子類別。子類別可以繼承父類別的屬性及方法,可以減少重複的程式碼。
在 swift 裡,使用繼承的方式可以用 :
,將要繼承的類別放在冒號後面,並且最多只能繼承一個類別
例如,宣告一個新的勇者類別 Brave
,讓它繼承 Role
類別
override
,覆寫原本的 run
方法fly
方法class Brave: Role {
override func run() {
print("run faster")
}
func fly() {
print("fly")
}
}
Brave
依然可以使用父類別 Role
中的屬性及方法,並且多了自己專有的方法,除了跑、跳之外,還可以飛let brave = Brave(hairColor: "orange", eyeColor: "blue")
print("hair color: \(brave.hairColor)")
print("eye color: \(brave.eyeColor)")
brave.run()
brave.jump()
brave.fly()
印出結果:
hair color: orange
eye color: blue
run faster
jump
fly
協定 (protocol) 的概念,其實和 interface 的概念非常相像,是一個尚未實作的、抽象的概念
它可以跟類別一樣定義一些屬性及方法,但是並不會實作,也就是方法內沒有內容。
SuperPower
的協定,讓勇者來使用useSuperPower()
方法的實作protocol SuperPower {
func useSuperPower()
}
Brave
類別遵循 SuperPower
協定:
Role
類別後方,使用逗號 ,
,再加上 SuperPower
協定。useSuperPower()
方法的內容,讓勇者具有瞬間移動的超能力class Brave: Role, SuperPower {
override func run() {
print("run faster")
}
func fly() {
print("fly")
}
func useSuperPower() {
print("move instantly!!")
}
}
let brave = Brave(hairColor: "orange", eyeColor: "blue")
brave.useSuperPower()
印出結果:
move instantly!!
Monster
,同樣繼承 Role
類別。我們希望勇者跟怪物同樣都可以使用超能力,並且他們的超能力不同,因此我們將 Monster
也遵循 SuperPower
協定class Monster: Role, SuperPower {
func useSuperPower() {
print("fireball!!")
}
}
let monster = Monster(hairColor: "red", eyeColor: "red")
monster.useSuperPower()
印出結果:
fireball!!
useSuperPower()
了,並且具有不同種類的超能力。而最初創建的人類角色,沒有遵循超能力協定 SuperPower
,因此也確實不能使用超能力。useSuperPower()
方法宣告在 Role
類別中,也不需要在一開始就定義他的方法內容,只需要宣告在抽象的協定中,並且只在使用到的地方實作方法即可。結構 (struct) 和類別 (class) 類似,可以宣告屬性及方法,但是結構不能繼承,不過它是可以使用協定的。
init
可以省略SuperPower
協定,並且實作 useSuperPower()
方法struct Brave: SuperPower {
var hairColor: String
var eyeColor: String
func fly() {
print("fly")
}
func useSuperPower() {
print("move")
}
}
let brave = Brave(hairColor: "orange", eyeColor: "blue")
print("hair color: \(brave.hairColor)")
print("eye color: \(brave.eyeColor)")
brave.fly()
brave.useSuperPower()
印出結果:
hair color: orange
eye color: blue
fly
move
從上述的範例,結構看起來感覺跟類別很像對吧,但是他們還是有差異的。
簡單來講,當我對一個結構的實體做修改,我可以確實只修改到它。
而當我對一個類別的實體做修改,有可能會有其他實體也一起被修改!原因是當修改類別的實體時,實際上是對它指向的位址做修改,當有其他實體也是指向同個位址時,就會一起被修改了。
structBrave2
做修改時,structBrave
還是維持原本的值 (blue)classBrave2
做修改時,classBrave
的值也變成新的值了 (green)struct StructBrave {
var hairColor: String
var eyeColor: String
}
class ClassBrave {
var hairColor: String
var eyeColor: String
init(hairColor: String, eyeColor: String) {
self.hairColor = hairColor
self.eyeColor = eyeColor
}
}
let structBrave = StructBrave(hairColor: "orange", eyeColor: "blue")
let classBrave = ClassBrave(hairColor: "orange", eyeColor: "blue")
var structBrave2 = structBrave
var classBrave2 = classBrave
structBrave2.eyeColor = "green"
classBrave2.eyeColor = "green"
print(structBrave.eyeColor)
print(classBrave.eyeColor)
印出結果:
blue
green
let
宣告實體,不能修改他的屬性
let structBrave = StructBrave(hairColor: "orange", eyeColor: "blue")
let classBrave = ClassBrave(hairColor: "orange", eyeColor: "blue")
structBrave.eyeColor = "green" // 報錯,不能修改常數
classBrave.eyeColor = "green" // 成功編譯,因 var eyeColor: String 為變數
以上是今日的介紹~
明天將進入 swift 基礎語法的最後一篇介紹,繼續加油吧!