swift 学习- 14 -- 继承
// 一個(gè)類可以繼承另一個(gè) 類的方法, 屬性和其他特征, 當(dāng)一個(gè)類繼承其他類時(shí), 繼承類叫子類, 被繼承類叫父類 或 (超類), 在 Swift 中, 繼承是區(qū)分 [類] 和其他類型的 一個(gè)基本特征
?
// 在 Swift 中, 類可以調(diào)用和訪問超類的方法, 屬性 和 下標(biāo), 并且可以重寫這些方法, 屬性 和 下標(biāo)來優(yōu)化或修改他們的行為
// Swift 會(huì)檢查你的重寫定義在超類中是否有匹配的定義, 一次確保你的重寫行為是正確的
?
// 可以為類中繼承來的屬性添加屬性觀察器, 這樣一來, 當(dāng)屬性值改變時(shí), 類就會(huì)被通知到, 可以為 任意屬性 添加 屬性觀察器,無論他原本被定義為 存儲(chǔ)屬性 還是 計(jì)算屬性
?
?
?
?
// 定義一個(gè)基類
// 不繼承于其他類的類, 稱之為 基類
// 注意 : Swift 中的類并不是 從一個(gè)通用的 基類繼承而來, 如果你不為你定義的類指定一個(gè) 超類 的話, 這個(gè)類就自動(dòng)成為 基類
?
?
// 一個(gè)例子定義了一個(gè)叫做 Vehicle 的基類, 這個(gè)基類聲明了一個(gè)名為 currentSpeed , 默認(rèn)值是 0.0 的存儲(chǔ)屬性 (屬性類型推斷為 Double), currentSpeed 屬性的值被一個(gè) String 類型的只讀計(jì)算型屬性 description 使用, 用來創(chuàng)建車輛的描述 . Vehicle 基類也定義了一個(gè)名為 makeNoise 的方法, 這個(gè)方法實(shí)際上部位 Vehicle 實(shí)例做任何事, 但之后將會(huì)被 Vehicle 的子類定制
?
class Vehicle{
? ? var currentSpeed = 0.0
? ? var description: String {
? ? ? ? return "traveling at \(currentSpeed) miles per hour"
? ? }
?? ?
? ? func makeNoise() {
? ? ? ? // 什么也不作
? ? }
}
?
?
let someVehicle = Vehicle()
print("Vehicle: \(someVehicle.description)")
?
?
?
?
// 子類生成
// 子類生成 指的是在一個(gè)已有類的基礎(chǔ)上創(chuàng)建一個(gè)新的類, 子類繼承超類的特性, 并且可以進(jìn)一步完善, 你還可以為子類添加新的特性
// 為了指明某個(gè)類的超類, 將超類名卸載子類名的后面, 用冒號(hào)分割:
?
class Bicycle: Vehicle{
? ? var hasBasket = false
}
?
// 新的 Bicycle 類自動(dòng)獲得 Vehicle 類的所有屬性 和 方法, 除了他所繼承的特性, Bicycle 類還定義了一個(gè)默認(rèn)值為 false 的存儲(chǔ)屬性 hasBasket (Bool 型)
?
// 默認(rèn)情況下,你創(chuàng)建的任何新的 Bicycle 實(shí)例將不會(huì)有一個(gè)籃子,但是可以為特定的 Bicycle 實(shí)例設(shè)置 hasBasket 屬性為 ture
?
let bicycle = Bicycle()
bicycle.hasBasket = true
?
// 還可以修改 Bicycle 實(shí)例所繼承的 currentSpeed 屬性, 和查詢實(shí)例所繼承的 descriotion 屬性:
bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.currentSpeed)")
?
?
// 子類還可以繼續(xù)被其它類所繼承 下面的示例為Bicycle創(chuàng)建了一個(gè)名為Tandem(雙人自行車)的子類:
?
?
class Tandem: Bicycle {
? ? var currentNumberOfPassengers = 0
}
?
?
// Tandem從Bicycle繼承了所有的屬性與方法,這又使它同時(shí)繼承了Vehicle的所有屬性與方法。Tandem也增加了一個(gè)新的叫做currentNumberOfPassengers的存儲(chǔ)型屬性,默認(rèn)值為0。
?
?
// 如果你創(chuàng)建了一個(gè)Tandem的實(shí)例,你可以使用它所有的新屬性和繼承的屬性,還能查詢從Vehicle繼承來的只讀屬性description:
?
?
let tandem = Tandem()
tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0
print("Tandem: \(tandem.description)")
// 打印:"Tandem: traveling at 22.0 miles per hour"
?
?
?
?
// 重寫
// 子類可以為繼承來的實(shí)例方法, 類方法, 實(shí)例屬性, 或 下標(biāo)提供自己定制實(shí)現(xiàn), 我們把這種行為叫做 重寫
?
// 如果要重寫某個(gè)特性, 你需要在重寫定義的前面加上 override 關(guān)鍵字, 這么做, 你就表明了你是想提供一個(gè)重寫版本, 而非錯(cuò)誤地提供一個(gè)相同的定義, 意外的重寫可能導(dǎo)致 不可預(yù)知的 錯(cuò)誤, 任何缺少 override 關(guān)鍵字的 重寫都會(huì)在編譯時(shí)診斷為 錯(cuò)誤
?
// override 關(guān)鍵字會(huì)提醒 Swift 編輯器去檢查該類的 超類,是否有匹配重寫版本的聲明, 這個(gè)檢查可以確保你的重寫定義是正確的
?
?
?
?
// 訪問超類的方法, 屬性 和 下標(biāo)
// 當(dāng)你在子類中重寫超類的方法,屬性 或 下標(biāo)時(shí), 有時(shí) 在你的重寫版本中 使用已經(jīng)存在的 超類實(shí)現(xiàn) 會(huì)大有裨益, 比如, 你完全可以完善已有實(shí)現(xiàn)的行為, 或在一個(gè)繼承來的變量中存儲(chǔ)一個(gè)修改過的值
?
// 在適當(dāng)?shù)牡胤? 你可以通過使用 super 前綴來訪問超類版本的方法, 屬性 或 下標(biāo)
// 1:? 在方法someMethod()的重寫實(shí)現(xiàn)中,可以通過super.someMethod()來調(diào)用超類版本的someMethod()方法。
// 2:? 在屬性someProperty的 getter 或 setter 的重寫實(shí)現(xiàn)中,可以通過super.someProperty來訪問超類版本的someProperty屬性。
// 3:? 在下標(biāo)的重寫實(shí)現(xiàn)中,可以通過super[someIndex]來訪問超類版本中的相同下標(biāo)。
?
?
?
?
// 重寫方法
// 在子類中, 你可以重寫繼承來的實(shí)例方法或類方法, 提供一個(gè)定制或替代的方法實(shí)現(xiàn)
?
class Train: Vehicle{
? ? override func makeNoise() {
? ? ? ? print("Choo Choo")
? ? }
}
?
// 這個(gè)例子定義了 Vehicle 的一個(gè)新的子類, 叫 Train, 它重寫了從 Vehicle 類繼承來的 makeNoise() 方法
?
let train = Train()
train.makeNoise()
?
?
?
?
// 重寫屬性
// 你可以重寫繼承來的實(shí)例屬性或類型屬性, 提供自己定制的 getter 和 setter,或添加屬性觀察器 使 重寫的屬性 也可以觀察值什么時(shí)候變化
?
?
?
// 重寫 屬性的 getter 和 setter?
// 你可以提供定制的 getter 和 setter 來重寫任意繼承來的屬性, 無論繼承來的屬性是存儲(chǔ)型的 還是 計(jì)算型屬性, 子類并不知道繼承來的屬性是 存儲(chǔ)型的 還是 計(jì)算型的, 它只知道繼承來的屬性會(huì)有一個(gè) 名字和類型 , 你在重寫一個(gè)屬性時(shí), 必須將它的 名字和類型 都寫出來, 這樣才能使編譯器 去檢查你重寫的屬性 是否與 超類中同名同類型的屬性 相匹配的
?
// 你可以將一個(gè)繼承來的 只讀屬性 重寫為 讀寫屬性,只需要在重寫版本的屬性里 提供 getter 和 setter 即可, 但是,你不能將一個(gè)繼承來的讀寫屬性 重寫為 一個(gè)只讀屬性
?
// 注意 : 如果你在重寫屬性中提供了 setter ,那么你也一定要提供 getter, 如果你不想在重寫版本中的 getter 里修改繼承來的屬性值, 你可以直接通過 super.someProperty 來返回繼承來的值, 其中 someProperty 是你要重寫的屬性的名字
?
?
class Car: Vehicle{
? ? var gear = 1
? ? override var description: String{
? ? ? ? return super.description + " in gear \(gear)"
? ? }
}
?
// 這個(gè)例子定義了一個(gè)新類,叫Car,它是Vehicle的子類。這個(gè)類引入了一個(gè)新的存儲(chǔ)型屬性叫做gear,默認(rèn)值為整數(shù)1。Car類重寫了繼承自Vehicle的description屬性,提供包含當(dāng)前檔位的自定義描述:
?
// 重寫的 description 屬性首先要調(diào)用 super.description 返回 Vehicle 類的 description 屬性 之后, Car 類版本的 description 在末尾增加了自定義內(nèi)容
?
let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: \(car.description)")
?
?
?
?
// 重寫屬性觀察器
// 你可以通過重寫屬性為一個(gè) 繼承來的 屬性 添加 屬性觀察器, 這樣一來, 當(dāng)繼承來的屬性值發(fā)生變化時(shí), 你就會(huì)被通知到, 無論哪個(gè)屬性原本是如何實(shí)現(xiàn)的
?
// 注意 : 你不可以為繼承來的常量存儲(chǔ)屬性 或 繼承來的只讀計(jì)算屬性添加 屬性觀察器, 這些屬性的值是不可以被設(shè)置的. 所以, 為他們提供 willSet 和 didSet 是不恰當(dāng)?shù)?/p>
// 此外, 你不可以同時(shí)提供重寫的 setter 和 重寫的 屬性觀察器, 如果你想觀察屬性值的變化, 并且你已經(jīng)為那個(gè)屬性提供了定制的 setter ,那么你在 setter 中就可以觀察到任何值的變化了
?
class AutomaticCar: Car{
? ? override var currentSpeed: Double{
? ? ? ? didSet{
? ? ? ? ? ? gear = Int(currentSpeed / 10.0) + 1
? ? ? ? }
? ? }
}
?
// 當(dāng)你設(shè)置 AutomaticCar 的 currentSprrd 屬性, 屬性的 didSet 觀察器就會(huì)自動(dòng)地設(shè)置 gear 屬性, 為新的速度選擇一個(gè)合適的檔位, 具體來說, 屬性觀察器將新的速度值除以 10 ,然后向下取得最接近的整數(shù)值, 最后加 1 來得到檔位 gear 的值,?
?
let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")
?
?
?
?
// 防止重寫
// 你可以通過把方法,屬性 或 下標(biāo)標(biāo)記為 final 來防止他們被重寫, 只需要在聲明關(guān)鍵字前 加上 final 修飾符即可
// 如 : final var , final func, final class func , final subscript
?
// 如果你重寫了帶有 final 標(biāo)記的方法, 屬性或者下標(biāo), 在編譯時(shí)或報(bào)錯(cuò),?
?
// 在類擴(kuò)展中的方法, 屬性 或 下標(biāo)也可以在擴(kuò)展的定義里標(biāo)記為 fnial
?
// 你可以通過在關(guān)鍵字 class 前添加 final 修飾符 (final class) 來將整個(gè)類標(biāo)記為 final 的, 這樣的類是不可被繼承的, 試圖繼承這樣的類會(huì)導(dǎo)致編譯錯(cuò)誤
?
轉(zhuǎn)載于:https://www.cnblogs.com/dingzhijie/p/6897322.html
總結(jié)
以上是生活随笔為你收集整理的swift 学习- 14 -- 继承的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Error opening zip fi
- 下一篇: 阿里1582.73亿营收背后的持续交付如