2016年2月9日 星期二

iOS筆記:Swift(4)

Methods

Methods are functions that are associated with a particular type. Classes, structures, and enumerations can all define instance methods, which encapsulate specific tasks and functionality for working with an instance of a given type. Classes, structures, and enumerations can also define type methods, which are associated with the type itself. Type methods are similar to class methods in Objective-C.

Structures and enumerations can define methods in Swift is a major difference from C and Objective-C. In Objective-C, classes are the only types that can define methods. In Swift, you can choose whether to define a class, structure, or enumeration, and still have the flexibility to define methods on the type you create.

Instance Methods

實例方法是屬於某個特定類別、結構或者列舉型別實例的方法。實例方法提供存取和修改實例屬性的方法或提供與實例目的相關的功能,並以此來支撐實例的功能。實例方法的語法與函式完全一致

    class Counter {
        var count = 0
        func increment() {
            ++count
        }
        func incrementBy(amount: Int) {
            count += amount
        }
        func reset() {
            count = 0
        }
    }

    let counter = Counter()
    // the initial counter value is 0
    counter.increment()
    // the counter's value is now 1
    counter.incrementBy(5)
    // the counter's value is now 6
    counter.reset()
    // the counter's value is now 0

The Counter class defines three instance methods:
* increment increments the counter by 1.
* incrementBy(amount: Int) increments the counter by a specified integer amount.
* reset resets the counter to zero.

Local and External Parameter Names for Methods

Function parameters can have both a local name (for use within the function’s body) and an external name (for use when calling the function), as described in Specifying External Parameter Names.

    class Counter {
        var count: Int = 0
        func incrementBy(amount: Int, numberOfTimes: Int) {
            count += amount * numberOfTimes
        }
    }

incrementBy(_:number Of Times:)方法有兩個參數: amount和numberOfTimes。默認情況下,Swift 只把amount當作一個局部名稱,但是把numberOfTimes即看作局部名稱又看作外部名稱。下面調用這個方法:

    let counter = Counter()
    counter.incrementBy(5, numberOfTimes: 3)
    // counter value is now 15

The self Property

型別的每一個實例都有一個隱含屬性叫做 self , self 完全等同於該實例本身。你可以在一個實例的實例方法中使用這個隱
含的 self 屬性來參考當前實例。

只要在一個方法中使用一個已知的屬性或者方法名稱,如果沒有明確的寫 self ,Swift 假定是指當前實例的屬性或者方法。

func increment() {
    self.count++
}

Modifying Value Types from Within Instance Methods

Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.
但是,如果你確實需要在某個具體的方法中修改結構或者列舉的屬性,你可以選擇變異(mutating)這個方法,然後方法就可以從方法內部改變它的屬性;並且它做的任何改變在方法結束時還會保留在原始結構中。

要使用變異方法, 將關鍵字mutating 放到方法的func關鍵字之前就可以了:

struct Point {
  var x = 0.0, y = 0.0
  mutating func moveByX(deltaX: Double, y deltaY: Double) {
    x += deltaX
    y += deltaY
  }
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y: 3.0)
println("The point is now at (\(somePoint.x), \(somePoint.y))")
// 輸出 "The point is now at (3.0, 4.0)"

Assigning to self Within a Mutating Method

變異方法能夠賦給隱含屬性self一個全新的實例。

enum TriStateSwitch {
  case Off, Low, High
  mutating func next() {
    switch self {
    case Off:
      self = Low
    case Low:
      self = High
    case High:
      self = Off
    }
  }
}
var ovenLight = TriStateSwitch.Low
ovenLight.next()
// ovenLight 現在等於 .High
ovenLight.next()
// ovenLight 現在等於 .Off

Inheritance

在 Swift 中,類別可以呼叫和存取超類別的方法,屬性和下標腳本(subscripts),並且可以重寫(override)這些方法,屬性和下標腳本來優化或修改它們的行為。

下面的範例定義了一個叫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類別的新實例,使用建構器語法呼叫上面的初始化器,即類別名後面跟一個空的小括號:

let someVehicle = Vehicle()

Subclassing

以下定義一個新的類別叫Bicycle,它繼承了Vehicle的特性:

class Bicycle: Vehicle {
    init() {
        super.init()
        numberOfWheels = 2
    }
}

Bicycle類別定義了一個建構器來設置它定制的特性(自行車只有2個輪子)。Bicycle的建構器呼叫了它父類別Vehicle的建構器 super.init(),以此確保在Bicycle類別試圖修改那些繼承來的屬性前Vehicle類別已經初始化過它們了。

不像 Objective-C,在 Swift 中,初始化器預設是不繼承的

Overriding

A subclass can provide its own custom implementation of an instance method, type method, instance property, type property, or subscript that it would otherwise inherit from a superclass. This is known as overriding.

如果要重寫某個特性,你需要在重寫定義的前面加上override關鍵字。
override關鍵字會提醒 Swift 編譯器去檢查該類別的超類別(或其中一個父類別)是否有匹配重寫版本的宣告。這個檢查可以確保你的重寫定義是正確的。任何缺少override關鍵字的重寫都會在編譯時被診斷為錯誤。

在合適的地方,你可以通過使用super前綴來存取超類別版本的方法,屬性或下標腳本:

  1. 在方法someMethod的重寫實作中,可以通過super.someMethod()來呼叫超類別版本的someMethod方法。
  2. 在屬性someProperty的 getter 或 setter 的重寫實作中,可以通過super.someProperty來存取超類別版本的someProperty屬性。
  3. 在下標腳本的重寫實作中,可以通過super[someIndex]來存取超類別版本中的相同下標腳本

Overriding Methods

You can override an inherited instance or type method to provide a tailored or alternative implementation of the method within your subclass.

下面的範例定義了Vehicle的一個新的子類別,叫Car,它重寫了從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中的description方法並非完全自定義,而是通過super.description使用了超類別Vehicle中的description方法,然後再追加一些額外的資訊,比如汽車的當前速度。

Preventing Overrides

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

沒有留言:

張貼留言