Playground - Class, Struct

再來就是要提重點的東西了!

class 和 struct 是用來建構整個程式重要的東西

兩者的差異在於:class 可以繼承其他 class,但是 struct 無法繼承

以下是宣告方式

class SomeClass {
	//...
}

struct SomeStruct {
	//...
}

注意,Swift 的 class 和 struct 命名慣例是大寫命名風格 UpperCamelCase

而屬性和方法則是 lowerCamelCase

例如 increaseCount, addTwoInts

舉個例子:

struct Resolution {
	var width = 0
	var height = 0
}

class CustomLabel {
	var resolution = Resolution()
	var isLabel = true
	var name: String?
}

實體化,就可以改變其中的值了

var someResolution = Resolution()
var someLabel = CustomLabel()

someResolution.width = 100
someLabel.resolution.height = 200

就是一直 下去就對了!

Struct 我們也可以直接給定初始值,class 就不能這樣做了~

var someResolution = Resolution(width: 200, height: 300)

sttuct 的 Getter 和 Setter 只存在於 computed properties

亦即是必須要被計算過的才能使用 Getter, Setter

以下就直接看別人的例子吧:

struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
    var center: Point {
    get {
        let centerX = origin.x + (size.width / 2)
        let centerY = origin.y + (size.height / 2)
        return Point(x: centerX, y: centerY)
    }
    set(newCenter) {
        origin.x = newCenter.x - (size.width / 2)
        origin.y = newCenter.y - (size.height / 2)
    }
    }
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
    size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
println("square.origin is now at (\(square.origin.x), \(square.origin.y))")

Struct 和 enum 是一種值型別

值型別的的例子像是 Int, String ….

那 struct 和 enum 也是,都是以值來操作的

Class 是參考型別

使用時機

struct:

  • 用來封裝少量相關的資料
  • 不需要繼承
  • 是 copy value 而不是 reference

例如:Label 的長寬, 三角形的三個點

Class 二三事

礙于篇幅關係,這邊簡單講解一些 class 比較重要的點

通常一個 class 裡面會有一些 variable 與 methods

通常還會有靜態的 variables, methods 或是 建構子 (constructor)

甚至是延遲載入一個變數

下面就簡單寫了一個 class 來說明這幾個部分

class Person {
    
    var name: String
    var height: Int!
    
    // 型別屬性 (靜態變數)
    class var isAnimal: Bool {
        return true
    }
    
    // 初始化時必定輸入 name, 必須知道初始化時變數所代表的意義
    init(name: String) {
        self.name = name
    }
    
    // 型別方法 (靜態方法)
    class func sayHi() -> String {
        return "Hi!"
    }
    
    func sayYa() -> String {
        return "Ya"
    }
    
    final func car(#title: String) -> String{
        return title
    }
    
    lazy var personalizedGreeting: String = {
        [unowned self] in
        return "Hello, \(self.name)!"
    }()
}

let person = Person(name: "Kerkerj")
println(person.personalizedGreeting)
println(person.car(title: "Toyota"))
println(person.sayYa())
println(Person.sayHi())
println(Person.isAnimal)

self 的意思就代表 class 自己,就字面上來看應該蠻好懂的

通常 lazy 的使用時機在於,

有個值需要被複雜或大量計算時,或是初始化時可能需要大量計算時,

我們可以加入 lazy,使該變數在需要操作時再計算

下面再簡單講一點繼承的東西

直接看例子,我設定了一個 class 稱為 Man,繼承自 Person

class Man: Person {
    class var sex: String {
        return "Male"
    }
    
    override init(name: String) {
        super.init(name: name)
    }
    
    override func sayYa() -> String {
        return "YAYA"
    }
    
    func sayYo() -> String {
        return "YO"
    }
}

let kerkerj = Man(name: "kerkerj")
println(kerkerj.name)
println(kerkerj.sayYa())
println(kerkerj.sayYo())
println(Man.sex)

可以觀察一下自動補完的選項,當輸入 kerkerj.

後面會出現除了 Man 這個 class 本身提供的變數與方法外,

還有 Person 的變數與方法,這就是因為 Man 繼承自 Person 的關係

Man 裡面覆寫了 init, sayYa 的方法,

原本 sayYa 只會出現一次 “YA”, 覆寫過後會出現兩次變成 “YAYA”

另外 Man 再多加了一個 sayYo 的方法

如果父類別的某些方法不想被覆寫,在關鍵字前加上 final

就可以防止被覆寫


以上是一些 class 和 struct 的特性