Swift教程之繼續詳解。本站提示廣大學習愛好者:(Swift教程之繼續詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是Swift教程之繼續詳解正文
一個類可以從別的一個類中繼續辦法,屬性或許其它的一些特征。當一個類繼續於別的一個類時,這個繼續的類哨子類,被繼續的類叫父類。繼續是Swift中類差別於其它類型的一個根本特點。
Swift中的類可以挪用父類的辦法,應用父類的屬性和下標,還可以依據須要應用重寫辦法或許屬性來從新界說和修正他們的一些特征。Swift可以贊助你檢討重寫的辦法和父類的辦法界說是符合的。
類還可認為它繼續的屬性添加不雅察者,如許可以可以或許讓它在一個屬性變更的時刻獲得告訴。屬性不雅察者可以被添加給任何屬性,不論它之前是存儲屬性照樣盤算屬性。
1、界說一個基類
任何一個不繼續於其它類的類被稱作基類
留意:Swift的類不是從一個全局基類繼續而來。在你編寫代碼的時,只需是在類的界說中沒有繼續自父類的類都是基類。
上面的例子界說了一個叫Vehicle的基類。基類包括兩個一切交通對象通用的屬性numberOfWheels和maxPassengers。這兩個屬性被一個叫description的辦法應用,經由過程前往一個String描寫來作為這個交通對象的特點:
class Vehicle {
var numberOfWheels: Int
var maxPassengers: Int
func description() -> String {
return "\(numberOfWheels) wheels; up to \(maxPassengers) passengers"
}
init() {
numberOfWheels = 0
maxPassengers = 1
}
}
這個交通對象類Vehicle還界說了一個結構函數來設置它的屬性。結構函數更多的說明在Initialization一章,然則為了解釋子類若何修正繼續的屬性,這裡須要扼要說明一下甚麼叫結構函數。
經由過程結構函數可以創立一個類型的實例。雖然結構函數不是辦法,然則它們在編碼的時刻應用了異常類似的語法。結構函數經由過程確保一切實例的屬性都是有用的來創立一個新的實例。
結構函數最簡略的情勢是應用init症結詞的一個相似辦法的函數,而且沒有任何參數:
init() {
// perform some initialization here
}
應用結構函數語法TypeName和空的兩個小括號來完成一個Vehicle實例的創立:
let someVehicle = Vehicle()
Vehicle的結構函數為屬性設置了一些初始值(numberOfWheels = 0 然後 maxPassengers = 1)。
Vehicle類界說的是一個通用的交通對象特征,它自己沒有太多意義,所以就須要沖界說它的一些屬性或許辦法來讓它具有現實的意義。
2、發生子類
發生子類就是依據一個已有的類發生新類的進程。子類繼續了父類的一些可以修正的特征。還可認為子類添加一些新的特征。
為了注解一個類是繼續自一個父類,須要將父類的稱號寫在子類的前面,而且用冒號分隔:
class SomeClass: SomeSuperclass {
// class definition goes here
}
上面的例子界說了一種特定叫Bicycle的交通對象。這個新類是基於已有的類Vehicle發生的。書寫方法是在類名Bicycle後加冒號加父類Vehicle名。
可以懂得為:
界說一個新的類叫Bicycle,它繼續了Vehicle的特征:
class Bicycle: Vehicle {
init() {
super.init()
numberOfWheels = 2
}
}
Bicycle是Vehicle的子類,Vehicle是Bicycle的父類。Bicycle類繼續了Vehicle一切的特點,好比maxPassengers和numberOfWheels屬性。你還可認為Bicycle類添加心的屬性。
Bicycle類也界說了結構函數,在這個結構函數中挪用了父類的結構函數super.init(),如許可以確保在Bicycle修正他們之前,父類曾經初始化了。
留意:跟Objective-C分歧的是,Swift中的結構函數沒有默許繼續。更多信息可以參考Initializer Inheritance and Overriding這一章節。
maxPassengers屬性在繼續自父類的時刻曾經被初始化了,關於Bicycle來講是准確的,是以不須要再做更改。然後numberOfWheels是纰謬的,所以被調換成了2.
不只屬性是繼續於Vehicle的,Bicycle還繼續了父類的辦法。假如你創立一個實例,然後挪用了曾經繼續的description辦法,可以獲得該交通對象的描寫而且看到它的屬性曾經被修正:
let bicycle = Bicycle()
println("Bicycle: \(bicycle.description())")
// Bicycle: 2 wheels; up to 1 passengers
子類自己也能夠作為父類被再次繼續:
class Tandem: Bicycle {
init() {
super.init()
maxPassengers = 2
}
}
下面的例子創立了Bicycle的子類,叫做tandem,也便可以兩小我一路騎的自行車。所以Tandem沒有修正numberOfWheels屬性,只是更新了maxPassengers屬性。
留意:子類只可以或許在結構的時刻修正變量的屬性,不克不及修正常量的屬性。
創立一個Tandem的實例,然後挪用description辦法檢討屬性能否被准確修正:
let tandem = Tandem()
println("Tandem: \(tandem.description())")
// Tandem: 2 wheels; up to 2 passengers
留意到description辦法也被Tandem繼續了。
3、重寫辦法
子類可以供給由父類繼續來的實例辦法,類辦法,實例屬性或許下標的特性化完成。這個特征被稱為重寫。
重寫一個由繼續而來的辦法須要在辦法界說前標注override症結詞。經由過程如許的操作可以確保你所要修正的這個辦法確切是繼續而來的,而不會湧現重寫毛病。毛病的重寫會形成一些弗成預知的毛病,所以假如假如不標志override症結詞的話,就會被在代碼編譯時報錯。
override症結詞還可以或許讓Swift編譯器檢討該類的父類能否有符合的辦法,以確保你的重寫是可用的,准確的。
拜訪父類辦法,屬性和下標
當在重寫子類繼續自父類的辦法,屬性或許下標的時刻,須要用到一部門父類已有的完成。好比你可以重界說已知的一個完成或許在繼續的變量中存儲一個修正的值。
恰當的時刻,可以經由過程應用super前綴來拜訪父類的辦法,屬性或許下標:
叫someMethod的重寫辦法可以在完成的時刻經由過程super.someMethod()挪用父類的someMethod辦法。
叫someProperty的重寫屬性可以在重寫完成getter或許setter的時刻經由過程super.someProperty挪用父類的someProperty。
叫someIndex的重寫下標可以在完成下標的時刻經由過程super[someIndex]來拜訪父類的下標。
復寫辦法
你可以在你的子類中完成定制的繼續於父類的實例辦法或許類辦法。
上面的例子演示的就是一個叫Car的Vehicle子類,重寫了繼續自Vehicle的description辦法。
class Car: Vehicle {
var speed: Double = 0.0
init() {
super.init()
maxPassengers = 5
numberOfWheels = 4
}
override func description() -> String {
return super.description() + "; "
+ "traveling at \(speed) mph"
}
}
Car中界說了一個新的Double類型的存儲屬性speed。這個屬性默許值是0.0,意思是每小時0英裡。Car還有一個自界說的結構函數,設置了最年夜乘客數為5,輪子數目是4.
Car重寫了繼續的description辦法,並在辦法名description前標注了override症結詞。
在description中並沒有給出了一個全新的描寫完成,照樣經由過程super.description應用了Vehicle供給的部門描寫語句,然後加上了本身界說的一些屬性,如以後速度。
假如你創立一個Car的實例,然後挪用description辦法,會發明描寫語句釀成了如許:
let car = Car()
println("Car: \(car.description())")
// Car: 4 wheels; up to 5 passengers; traveling at 0.0 mph
復寫屬性
你還可以供給繼續自父類的實例屬性或許類屬性的特性化getter和setter辦法,或許是添加屬性不雅察者來完成重寫的屬性可以不雅察到繼續屬性的更改。
重寫屬性的Getters和Setters
不論在源類中繼續的這個屬性是存儲屬性照樣盤算屬性,你都可以供給一個定制的getter或許setter辦法來重寫這個繼續屬性。子類普通不會曉得這個繼續的屬性原來是存儲屬性照樣盤算屬性,然則它曉得這個屬性有特定的名字和類型。在重寫的時刻須要指明屬性的類型和名字,好讓編譯器可以檢討你的重寫能否與父類的屬性符合。
你可以將一個只讀的屬性經由過程提那家getter和setter繼續為可讀寫的,然則反之弗成。
留意:假如你為一個重寫屬性供給了setter辦法,那末也須要供給getter辦法。假如你不想在getter中修正繼續的屬性的值,可以在getter中應用super.someProperty便可,鄙人面SpeedLimitedCar例子中也是如許。
上面的例子界說了一個新類SpeedLimitedCar,是Car的一個子類。這個類表現一個顯示在40碼一下的車輛。經由過程重寫繼續的speed屬性來完成:
class SpeedLimitedCar: Car {
override var speed: Double {
get {
return super.speed
}
set {
super.speed = min(newValue, 40.0)
}
}
}
每當你要設置speed屬性的時刻,setter都邑檢討新值能否比40年夜,兩者中較小的值會被設置給SpeedLimitedCar。
假如你測驗考試為speed設置跨越40的值,description的輸入仍然照樣40:
let limitedCar = SpeedLimitedCar()
limitedCar.speed = 60.0
println("SpeedLimitedCar: \(limitedCar.description())")
// SpeedLimitedCar: 4 wheels; up to 5 passengers; traveling at 40.0 mph
重寫屬性不雅察者
你可使用屬性重寫為繼續的屬性添加不雅察者。這類做法可讓你不管這個屬性之前是若何完成的,在繼續的這個屬性變更的時刻都能獲得提示。更多相干的信息可以參考Property Observers這章。
留意:不克不及為繼續的常量存儲屬性或許是只讀盤算屬性添加不雅察者。這些屬性值是不克不及被修正的,是以不合適在重寫完成時添加willSet或許didSet辦法。
留意:不克不及同時界說重寫setter和重寫屬性不雅察者,假如想要不雅察屬性值的變更,而且又為該屬性給出了定制的setter,那只須要在setter中直接取得屬性值的變更就好了。
上面的代碼演示的是一個新類AutomaticCar,也是Car的一個子類。這個類注解一個具有主動變速箱的汽車,可以依據如今的速度主動選擇檔位,並在description中輸入以後檔位:
class AutomaticCar: Car {
var gear = 1
override var speed: Double {
didSet {
gear = Int(speed / 10.0) + 1
}
}
override func description() -> String {
return super.description() + " in gear \(gear)"
}
}
如許便可以完成,每次你設置speed的值的時刻,didSet辦法都邑被挪用,來看檔位能否須要變更。gear是由speed除以10加1盤算得來,所以當速度為35的時刻,gear檔位為4:
let automatic = AutomaticCar()
automatic.speed = 35.0
println("AutomaticCar: \(automatic.description())")
// AutomaticCar: 4 wheels; up to 5 passengers; traveling at 35.0 mph in gear 4
4、制止重寫
你可以經由過程標志final症結詞來制止重寫一個類的辦法,屬性或許下標。在界說的症結詞後面標注@final屬性便可。
在子類中任未嘗試重寫父類的final辦法,屬性或許下標的行動都邑在編譯時報錯。異樣在擴大中為類添加的辦法,屬性或許下標也能夠被標志為final。
還可以在類症結詞class前應用@final標志一全部類為final(@final class)。任何子類測驗考試繼續這個父類時都邑在編譯時報錯。