100 Days of Swift - Day 10 - 類Classes
10.0 摘要
- 類和結(jié)構(gòu)類似创译,都可以使用屬性和方法創(chuàng)建自己的類型。
- 類可以繼承,并獲得父類的所有屬性和方法旱眯。
- 用final關(guān)鍵字標記一個類,其他類無法繼承。
- 方法重寫允許子類用新的實現(xiàn)替換父類中的方法删豺。
- 當兩個變量指向同一個類實例時共虑,它們指向同一塊內(nèi)存,——改變一個會改變另一個呀页。
- 類有一個析構(gòu)函數(shù)妈拌,在類的實例銷毀時運行。
- 類不同于結(jié)構(gòu)體那樣強地強制常量蓬蝶,如果屬性聲明為變量尘分,則無論如何創(chuàng)建類實例,都可以更改它丸氛。
10.1 創(chuàng)建自定義類
- 類和結(jié)構(gòu)體類似培愁,可以創(chuàng)建新的數(shù)據(jù)結(jié)構(gòu),擁有屬性和方法缓窜。
- 類可以繼承定续,而結(jié)構(gòu)體無法繼承。
- 結(jié)構(gòu)體擁有默認成員初始化構(gòu)造器禾锤,而類沒有默認成員初始化構(gòu)造器私股,需要創(chuàng)建自定義初始化構(gòu)造器。
- Copy結(jié)構(gòu)體屬于深copy恩掷,每次都會創(chuàng)建一個新變量倡鲸,而類的copy 默認是淺copy指向源數(shù)據(jù),不會開辟新的內(nèi)存螃成。
- 類有析構(gòu)函數(shù)旦签,在對象被銷毀時調(diào)用,而結(jié)構(gòu)體沒有寸宏。
- 類的常亮實例對象可以隨意修改屬性變量宁炫,而結(jié)構(gòu)體常量不可以修改其屬性變量。
class Dog {
var name: String
var breed: String
init(name: String, breed: String) {
self.name = name
self.breed = breed
}
}
// 創(chuàng)建類的實例對象和結(jié)構(gòu)體類似氮凝,調(diào)用初始化方法羔巢,傳入成員初始值即可
let poppy = Dog(name: "Poppy", breed: "Poodle")
10.2 類繼承 Class inheritance
- 類可以通過繼承獲得父類的所有屬性和方法,也可以創(chuàng)建只屬于自己的屬性和方法罩阵。
class Dog {
var name: String
var breed: String
init(name: String, breed: String) {
self.name = name
self.breed = breed
}
}
// Poodle 繼承自 Dog,無自定義初始化構(gòu)造方法
class Poodle: Dog {
}
// 默認可以調(diào)用父類初始化方法
let poodle = Poodle(name: "Poodle旺財", breed: "Poodle")
// Poodle 繼承自 Dog竿秆,自定義初始化構(gòu)造器,通過super關(guān)鍵字可以調(diào)用父類的初始化構(gòu)造器進行初始化
class Poodle: Dog {
init(name: String) {
super.init(name: name, breed: "Poodle")
}
}
//
let poodle = Poodle(name: "Poodle旺財")
10.3 重載方法
- 子類方法用overriding修飾稿壁,覆蓋父類方法幽钢,自定義實現(xiàn)稱之為重載。
class Dog {
func makeNoise() {
print("Woof!")
}
}
// 繼承Dog
class Poodle: Dog {
}
// 調(diào)用父類方法
let poppy = Poodle()
poppy.makeNoise()
// Woof!
class Poodle: Dog {
override func makeNoise() {
print("Yip!")
}
}
let poppy = Poodle()
poppy.makeNoise()
// Yip!
- 非子類用overriding修飾方法編譯器會報錯傅是。
- 重載目的是子類復(fù)用父類方法并在其基礎(chǔ)上擴展匪燕,或者子類需要和父類不同的實現(xiàn)蕾羊。
10.4 Final classes
- 非繼承類,類默認可以被繼承帽驯,從而構(gòu)建復(fù)雜有序的類簇結(jié)構(gòu)龟再,但如果為了保持類簡單不可被繼承,需要使用final關(guān)鍵字修飾類尼变。
- 非繼承類不可重載方法利凑。
final class Dog {
var name: String
var breed: String
init(name: String, breed: String) {
self.name = name
self.breed = breed
}
}
10.5 Copying objects
- 結(jié)構(gòu)體和類的copy有所不同,
- 類對象的copy 是淺copy嫌术,兩個對象內(nèi)存指向同一區(qū)域哀澈,一改全改,
class Singer {
var name = "Taylor Swift"
}
var singer = Singer()
print(singer.name)
var singerCopy = singer
singerCopy.name = "Justin Bieber"
print(singer.name)
// Justin Bieber
print(singerCopy.name)
// Justin Bieber
- 結(jié)構(gòu)體對象copy則是深copy度气,copy出來的對象和源對象屬于兩個不同的對象日丹,只是數(shù)據(jù)一樣。
struct Singer {
var name = "Taylor Swift"
}
var singer = Singer()
var singerCopy = singer
singerCopy.name = "Justin Bieber"
print(singer.name)
// Taylor Swift
print(singerCopy.name)
// Justin Bieber
- 結(jié)構(gòu)體是值類型蚯嫌,而類是引用類型”铮可根據(jù)不同場景選擇使用择示。
10. 6 析構(gòu)函數(shù) Deinitializers
- 類有析構(gòu)函數(shù),而結(jié)構(gòu)體沒有晒旅,析構(gòu)函數(shù)是類對象生命周期函數(shù)之一栅盲,當類對象被銷毀時調(diào)用。
class Person {
var name = "John Doe"
init() {
print("\(name) is alive!")
}
func printGreeting() {
print("Hello, I'm \(name)")
}
}
deinit {
print("\(name) is no more!")
}
for _ in 1...3 {
let person = Person()
person.printGreeting()
// Hello, I'm John Doe
// John Doe is no more!
}
- 結(jié)構(gòu)體是值類型废恋,存儲在棧區(qū)谈秫,由系統(tǒng)管理生命周期,copy一次產(chǎn)生一個新對象鱼鼓,使用完系統(tǒng)自動回收拟烫。
而類是引用類型,由ARC 管理生命周期迄本,copy一次引用計數(shù)加一硕淑,銷毀一次則引用計數(shù)減一。直至引用計數(shù)為0時執(zhí)行析構(gòu)函數(shù)嘉赎,被系統(tǒng)回收置媳。
10.7 可變能力Mutability
- 類變量可以隨意修改其屬性變量,即便類對象是常量類型
- 結(jié)構(gòu)體變量不可以隨意修改其屬性變量公条,如需修改屬性變量需要用mutating關(guān)鍵字修飾方法拇囊,編譯器則允許該方法可修改屬性變量。
class Singer {
var name = "Taylor Swift"
}
let taylor = Singer()
// 常量類對象修改屬性變量
taylor.name = "Ed Sheeran"
print(taylor.name)
// 類對象禁止修改常量屬性
class Singer {
let name = "Taylor Swift"
}