在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ 繼承(Inheritance)
方法 - Methods
關(guān)于 Swift
下標(biāo)腳本(Subscripts)
類和結(jié)構(gòu)體
類型轉(zhuǎn)換(Type Casting)
控制流
析構(gòu)過程(Deinitialization)
集合類型 (Collection Types)
構(gòu)造過程(Initialization)
Optional Chaining
枚舉(Enumerations)
自動引用計(jì)數(shù)
繼承(Inheritance)
擴(kuò)展(Extensions)
泛型
字符串和字符(Strings and Characters)
函數(shù)(Functions)
高級運(yùn)算符
訪問控制
基本運(yùn)算符
嵌套類型
閉包(Closures)
協(xié)議
屬性 (Properties)

繼承(Inheritance)

一個(gè)類可以繼承(inherit)另一個(gè)類的方法(methods),屬性(property)和其它特性。當(dāng)一個(gè)類繼承其它類時(shí),繼承類叫子類(subclass),被繼承類叫超類(或父類,superclass)。在 Swift 中,繼承是區(qū)分「類」與其它類型的一個(gè)基本特征。

在 Swift 中,類可以調(diào)用和訪問超類的方法,屬性和下標(biāo)腳本(subscripts),并且可以重寫(override)這些方法,屬性和下標(biāo)腳本來優(yōu)化或修改它們的行為。Swift 會檢查你的重寫定義在超類中是否有匹配的定義,以此確保你的重寫行為是正確的。

可以為類中繼承來的屬性添加屬性觀察器(property observer),這樣一來,當(dāng)屬性值改變時(shí),類就會被通知到??梢詾槿魏螌傩蕴砑訉傩杂^察器,無論它原本被定義為存儲型屬性(stored property)還是計(jì)算型屬性(computed property)。

定義一個(gè)基類(Base class)

不繼承于其它類的類,稱之為基類(base calss)。

注意:
Swift 中的類并不是從一個(gè)通用的基類繼承而來。如果你不為你定義的類指定一個(gè)超類的話,這個(gè)類就自動成為基類。

下面的例子定義了一個(gè)叫Vehicle的基類。這個(gè)基類聲明了一個(gè)名為currentSpeed,默認(rèn)值是0.0的存儲屬性(屬性類型推斷為Double)。currentSpeed屬性的值被一個(gè)String 類型的只讀計(jì)算型屬性description使用,用來創(chuàng)建車輛的描述。

Vehicle基類也定義了一個(gè)名為makeNoise的方法。這個(gè)方法實(shí)際上不為Vehicle實(shí)例做任何事,但之后將會被Vehicle的子類定制

    class Vehicle {
        var currentSpeed = 0.0
        var description: String {
            return "traveling at \(currentSpeed) miles per hour"
        }
        func makeNoise() {
            // 什么也不做-因?yàn)檐囕v不一定會有噪音
        }
    }

您可以用初始化語法創(chuàng)建一個(gè)Vehicle的新實(shí)例,即 TypeName后面跟一個(gè)空括號:

    let someVehicle = Vehicle()

現(xiàn)在已經(jīng)創(chuàng)建了一個(gè)Vehicle的新實(shí)例,你可以訪問它的description屬性來打印車輛的當(dāng)前速度。

    println("Vehicle: \(someVehicle.description)")
    // Vehicle: traveling at 0.0 miles per hour

子類生成(Subclassing)

子類生成(Subclassing)指的是在一個(gè)已有類的基礎(chǔ)上創(chuàng)建一個(gè)新的類。子類繼承超類的特性,并且可以優(yōu)化或改變它。你還可以為子類添加新的特性。

為了指明某個(gè)類的超類,將超類名寫在子類名的后面,用冒號分隔:

    class SomeClass: SomeSuperclass {
        // 類的定義
    }

下一個(gè)例子,定義一個(gè)更具體的車輛類叫Bicycle。這個(gè)新類是在 Vehicle類的基礎(chǔ)上創(chuàng)建起來。因此你需要將Vehicle類放在 Bicycle類后面,用冒號分隔。

我們可以將這讀作:

“定義一個(gè)新的類叫Bicycle,它繼承了Vehicle的特性”;

    class Bicycle: Vehicle {
        var hasBasket = false
    }

新的Bicycle類自動獲得Vehicle類的所有特性,比如 currentSpeeddescription屬性,還有它的makeNoise方法。

除了它所繼承的特性,Bicycle類還定義了一個(gè)默認(rèn)值為false的存儲型屬性hasBasket(屬性推斷為Bool)。

默認(rèn)情況下,你創(chuàng)建任何新的Bicycle實(shí)例將不會有一個(gè)籃子,創(chuàng)建該實(shí)例之后,你可以為特定的Bicycle實(shí)例設(shè)置hasBasket屬性為ture

    let bicycle = Bicycle()
    bicycle.hasBasket = true

你還可以修改Bicycle實(shí)例所繼承的currentSpeed屬性,和查詢實(shí)例所繼承的description屬性:

    bicycle.currentSpeed = 15.0
    println("Bicycle: \(bicycle.description)")
    // Bicycle: traveling at 15.0 miles per hour

子類還可以繼續(xù)被其它類繼承,下面的示例為Bicycle創(chuàng)建了一個(gè)名為Tandem(雙人自行車)的子類:

    class Tandem: Bicycle {
        var currentNumberOfPassengers = 0
    }

TandemBicycle繼承了所有的屬性與方法,這又使它同時(shí)繼承了Vehicle的所有屬性與方法。Tandem也增加了一個(gè)新的叫做currentNumberOfPassengers的存儲型屬性,默認(rèn)值為0。

如果你創(chuàng)建了一個(gè)Tandem的實(shí)例,你可以使用它所有的新屬性和繼承的屬性,還能查詢從Vehicle繼承來的只讀屬性description

    let tandem = Tandem()
    tandem.hasBasket = true
    tandem.currentNumberOfPassengers = 2
    tandem.currentSpeed = 22.0
    println("Tandem: \(tandem.description)")
    // Tandem: traveling at 22.0 miles per hour

重寫(Overriding)

子類可以為繼承來的實(shí)例方法(instance method),類方法(class method),實(shí)例屬性(instance property),或下標(biāo)腳本(subscript)提供自己定制的實(shí)現(xiàn)(implementation)。我們把這種行為叫重寫(overriding)。

如果要重寫某個(gè)特性,你需要在重寫定義的前面加上override關(guān)鍵字。這么做,你就表明了你是想提供一個(gè)重寫版本,而非錯(cuò)誤地提供了一個(gè)相同的定義。意外的重寫行為可能會導(dǎo)致不可預(yù)知的錯(cuò)誤,任何缺少override關(guān)鍵字的重寫都會在編譯時(shí)被診斷為錯(cuò)誤。

override關(guān)鍵字會提醒 Swift 編譯器去檢查該類的超類(或其中一個(gè)父類)是否有匹配重寫版本的聲明。這個(gè)檢查可以確保你的重寫定義是正確的。

訪問超類的方法,屬性及下標(biāo)腳本

當(dāng)你在子類中重寫超類的方法,屬性或下標(biāo)腳本時(shí),有時(shí)在你的重寫版本中使用已經(jīng)存在的超類實(shí)現(xiàn)會大有裨益。比如,你可以優(yōu)化已有實(shí)現(xiàn)的行為,或在一個(gè)繼承來的變量中存儲一個(gè)修改過的值。

在合適的地方,你可以通過使用super前綴來訪問超類版本的方法,屬性或下標(biāo)腳本:

  • 在方法someMethod的重寫實(shí)現(xiàn)中,可以通過super.someMethod()來調(diào)用超類版本的someMethod方法。
  • 在屬性someProperty的 getter 或 setter 的重寫實(shí)現(xiàn)中,可以通過super.someProperty來訪問超類版本的someProperty屬性。
  • 在下標(biāo)腳本的重寫實(shí)現(xiàn)中,可以通過super[someIndex]來訪問超類版本中的相同下標(biāo)腳本。

重寫方法

在子類中,你可以重寫繼承來的實(shí)例方法或類方法,提供一個(gè)定制或替代的方法實(shí)現(xiàn)。

下面的例子定義了Vehicle的一個(gè)新的子類,叫Train,它重寫了從Vehicle類繼承來的makeNoise方法:

    class Train: Vehicle {
        override func makeNoise() {
            println("Choo Choo")
        }
    }

如果你創(chuàng)建一個(gè)Train的新實(shí)例,并調(diào)用了它的makeNoise方法,你就會發(fā)現(xiàn)Train版本的方法被調(diào)用:

    let train = Train()
    train.makeNoise()
    // prints "Choo Choo"

重寫屬性

你可以重寫繼承來的實(shí)例屬性或類屬性,提供自己定制的getter和setter,或添加屬性觀察器使重寫的屬性觀察屬性值什么時(shí)候發(fā)生改變。

重寫屬性的Getters和Setters

你可以提供定制的 getter(或 setter)來重寫任意繼承來的屬性,無論繼承來的屬性是存儲型的還是計(jì)算型的屬性。子類并不知道繼承來的屬性是存儲型的還是計(jì)算型的,它只知道繼承來的屬性會有一個(gè)名字和類型。你在重寫一個(gè)屬性時(shí),必需將它的名字和類型都寫出來。這樣才能使編譯器去檢查你重寫的屬性是與超類中同名同類型的屬性相匹配的。

你可以將一個(gè)繼承來的只讀屬性重寫為一個(gè)讀寫屬性,只需要你在重寫版本的屬性里提供 getter 和 setter 即可。但是,你不可以將一個(gè)繼承來的讀寫屬性重寫為一個(gè)只讀屬性。

注意:
如果你在重寫屬性中提供了 setter,那么你也一定要提供 getter。如果你不想在重寫版本中的 getter 里修改繼承來的屬性值,你可以直接通過super.someProperty來返回繼承來的值,其中someProperty是你要重寫的屬性的名字。

以下的例子定義了一個(gè)新類,叫Car,它是Vehicle的子類。這個(gè)類引入了一個(gè)新的存儲型屬性叫做gear,默認(rèn)為整數(shù)1。Car類重寫了繼承自Vehicle的description屬性,提供自定義的,包含當(dāng)前檔位的描述:

    class Car: Vehicle {
        var gear = 1
        override var description: String {
            return super.description + " in gear \(gear)"
        }
    }

重寫的description屬性,首先要調(diào)用super.description返回Vehicle類的description屬性。之后,Car類版本的description在末尾增加了一些額外的文本來提供關(guān)于當(dāng)前檔位的信息。

如果你創(chuàng)建了Car的實(shí)例并且設(shè)置了它的gearcurrentSpeed屬性,你可以看到它的description返回了Car中定義的description

    let car = Car()
    car.currentSpeed = 25.0
    car.gear = 3
    println("Car: \(car.description)")
    // Car: traveling at 25.0 miles per hour in gear 3

重寫屬性觀察器(Property Observer)

你可以在屬性重寫中為一個(gè)繼承來的屬性添加屬性觀察器。這樣一來,當(dāng)繼承來的屬性值發(fā)生改變時(shí),你就會被通知到,無論那個(gè)屬性原本是如何實(shí)現(xiàn)的。關(guān)于屬性觀察器的更多內(nèi)容,請看屬性觀察器

注意:
你不可以為繼承來的常量存儲型屬性或繼承來的只讀計(jì)算型屬性添加屬性觀察器。這些屬性的值是不可以被設(shè)置的,所以,為它們提供willSetdidSet實(shí)現(xiàn)是不恰當(dāng)。此外還要注意,你不可以同時(shí)提供重寫的 setter 和重寫的屬性觀察器。如果你想觀察屬性值的變化,并且你已經(jīng)為那個(gè)屬性提供了定制的 setter,那么你在 setter 中就可以觀察到任何值變化了。

下面的例子定義了一個(gè)新類叫AutomaticCar,它是Car的子類。AutomaticCar表示自動擋汽車,它可以根據(jù)當(dāng)前的速度自動選擇合適的擋位:

    class AutomaticCar: Car {
        override var currentSpeed: Double {
            didSet {
                gear = Int(currentSpeed / 10.0) + 1
            }
        }
    }

當(dāng)你設(shè)置AutomaticCarcurrentSpeed屬性,屬性的didSet觀察器就會自動地設(shè)置gear屬性,為新的速度選擇一個(gè)合適的擋位。具體來說就是,屬性觀察器將新的速度值除以10,然后向下取得最接近的整數(shù)值,最后加1來得到檔位gear的值。例如,速度為10.0時(shí),擋位為1;速度為35.0時(shí),擋位為4:

    let automatic = AutomaticCar()
    automatic.currentSpeed = 35.0
    println("AutomaticCar: \(automatic.description)")
    // AutomaticCar: traveling at 35.0 miles per hour in gear 4

防止重寫

你可以通過把方法,屬性或下標(biāo)腳本標(biāo)記為final來防止它們被重寫,只需要在聲明關(guān)鍵字前加上@final特性即可。(例如:final var, final func, final class func, 以及 final subscript

如果你重寫了final方法,屬性或下標(biāo)腳本,在編譯時(shí)會報(bào)錯(cuò)。在擴(kuò)展中,你添加到類里的方法,屬性或下標(biāo)腳本也可以在擴(kuò)展的定義里標(biāo)記為 final。

你可以通過在關(guān)鍵字class前添加final特性(final class)來將整個(gè)類標(biāo)記為 final 的,這樣的類是不可被繼承的,否則會報(bào)編譯錯(cuò)誤。