Swift學習筆記第六篇(類,屬性,方法)

Deft_MKJing宓珂璟發表於2017-06-23

類定義

我們通過關鍵字class和struct來分別表示類和結構體,並在一對大括號中定義它們的具體內容

/*
 class SomeClass {
 // class definition goes here
 }
 struct SomeStructure {
 // structure definition goes here
 }
 */

類和結構體共同點
/*
1.定義屬性用於儲存值
2.定義方法用於提供功能
3.定義附屬指令碼用於訪問值
4.定義構造器用於生成初始化值
5.通過擴充套件以增加預設實現的功能
6.符合協議以對某類提供標準功能
*/

/*
類和結構體共同點
1.繼承允許一個類繼承另一個類的特徵
2.型別轉換允許在執行時檢查和解釋一個類例項的型別
3.解構器允許一個類例項釋放任何其所被分配的資源
4.引用計數允許對一個類的多次引用
*/

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

class JackModel{
    var area = Area()
    var isFemale = false
    var name : String?
}


let someArea = Area()
let someJackModel = JackModel()

print("The width of Area is \(someArea.width)")
someJackModel.area.width = 1040
print("The width of Area is \(someJackModel.area.width)")

注意: 與 Objective-C 語言不同的是,Swift 允許直接設定結構體屬性的子屬性。上面的最後一個例子,就是直接設定了someVideoMode中resolution屬性的width這個子屬性,以上操作並不需要重新設定resolution屬性

// 結構體型別的成員逐一構造器 類就沒有這種逐一構造方法
let hehe = Area(width:100,height:200)
print(hehe.height)

/*
1.結構體和列舉—>值型別被賦予給一個變數,常數或者本身被傳遞給一個函式的時候,實際上操作的是其的拷貝。
2.類——————>與值型別不同,引用型別在被賦予到一個變數、常量或者被傳遞到一個函式時,操作的是引用,其並不是拷貝。因此,引用的是已存在的例項本身而不是其拷貝

*/

恆等運算子

判斷兩個類是否完全相等
// 恆等運算子
/*
因為類是引用型別,有可能有多個常量和變數在後臺同時引用某一個類例項。(
對於結構體和列舉來說,這並不成立。因為它們作為值型別,在被賦予到常量、變數或者傳遞到函式時,其值總是會被拷貝。
1.請注意“等價於”(用三個等號表示,===) 與“等於”(用兩個等號表示,==)的不同
2.“等價於”表示兩個類型別(class type)的常量或者變數引用同一個類例項。
3.“等於”表示兩個例項的值“相等”或“相同”
*/

類和結構體的選擇

/*
然而,結構體例項總是通過值傳遞,類例項總是通過引用傳遞。
這意味兩者適用不同的任務。當你在考慮一個工程專案的資料構造和功能的時候,你需要決定每個資料構造是定義成類還是結構體。
1.結構體的主要目的是用來封裝少量相關簡單資料值。
2.有理由預計一個結構體例項在賦值或傳遞時,封裝的資料將會被拷貝而不是被引用。
3.任何在結構體中儲存的值型別屬性,也將會被拷貝,而不是被引用。
4.結構體不需要去繼承另一個已存在型別的屬性或者行為。
5.實際中,這意味著絕大部分的自定義資料構造都應該是類,而非結構體。
*/

值傳遞和值copy

/*
Swift 中字串(String),陣列(Array)和字典(Dictionary)型別均以結構體的形式實現。
這意味著String,Array,Dictionary型別資料被賦值給新的常量(或變數),或者被傳入函式(或方法)中時,它們的值會發生拷貝行為(值傳遞方式
Objective-C中字串(NSString),陣列(NSArray)和字典(NSDictionary)型別均以類的形式實現,這與Swfit中以值傳遞方式是不同的。NSString,NSArray,NSDictionary在發生賦值或者傳入函式(或方法)時,不會發生值拷貝,而是傳遞已存在例項的引用。
*/

屬性

/*
簡單來說,一個儲存屬性就是儲存在特定類或結構體的例項裡的一個常量或變數,
儲存屬性可以是變數儲存屬性(用關鍵字var定義),也可以是常量儲存屬性(用關鍵字let定義)
*/

// 主要介紹下延遲儲存屬性 lazy關鍵字
/*
1.可以理解為懶載入,這裡有關鍵字給屬性輔助
2.必須將延遲儲存屬性宣告成變數(使用var關鍵字),因為屬性的值在例項構造完成之前可能無法得到。而常量屬性在構造過程完成之前必須要有初始值,因此無法宣告成延遲屬性。
*/

class DataImporter {
    /*
     DataImporter 是一個將外部檔案中的資料匯入的類。
     這個類的初始化會消耗不少時間。
     因此一開始沒用到就初始化會沒必要 用懶載入進行操作
     */
    var fileName = "data.txt"
}

class DataManager {
    lazy var importer = DataImporter()
    var data = String()
    // 這是提供資料管理功能
}

let manager = DataManager()
manager.data.append("mikejing")
manager.data.append("!!!")
print(manager.data)
// DataImporter 例項的 importer 屬性還沒有被建立
print(manager.importer.fileName)
// DataImporter 例項的 importer 屬性現在被建立了
// 輸出 "data.txt”

getter setter didSet willSet方法

// getter setter willSet didSet
class StepCounter {
    var totalSteps: Int = 0 {

//        get {
//            return totalSteps
//        }
//        set {
//            totalSteps = newValue
//        }
        // 在設定setter方法之前呼叫
        willSet(newTotalSteps) {
            print("will set \(newTotalSteps)")
        }
        // 賦值的時候呼叫
        didSet {
            print("did set")
            if totalSteps > oldValue  {
                print("add \(totalSteps - oldValue) steps")
            }
        }
    }
}

let name = StepCounter()
name.totalSteps = 100
// will set 100
// did set
// add 100 steps
name.totalSteps = 540
/*
 will set 540
 did set
 add 440 steps
 */
name.totalSteps = 775
/*
 will set 775
 did set
 add 235 steps
 */


func方法

結構體和列舉能夠定義方法是 Swift 與 C/Objective-C 的主要區別之一。在 Objective-C 中,類是唯一能定義方法的型別。但在 Swift 中,你不僅能選擇是否要定義一個類/結構體/列舉,還能靈活的在你建立的型別(類/結構體/列舉)上定義方法。

class Counter {
    var count = 0
    func increment() {
        count += 1
    }
    // by是外部引數  amount 是內部引數
    func increment(by 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.increment(by: 5)
// the counter's value is now 6
counter.reset()
// the counter's value is now 0

例項方法中修改值型別的屬性 mutating

/* 1.在示例方法中修改值型別 Modifying Value Types from Within Instance Methods
* 2.結構體和列舉是值型別。一般情況下,值型別的屬性不能在它的例項方法中被修改。
* 3.mutating方法就可以從方法內部改變它的屬性
*/

// 方法一 修改原來建立的型別變數
struct Point{
    var x = 0.0
    var y = 0.0
    mutating func movePoint(x deltaX:Double,y deltaY:Double) {
        x += deltaX
        y += deltaY
    }
}

var pointA = Point(x:1.0,y:1.0)
print("x=\(pointA.x),y=\(pointA.y)")
pointA.movePoint(x: 9, y: 9)
print("x=\(pointA.x),y=\(pointA.y)")

注意:不能在結構體型別常量上呼叫變異方法,因為常量的屬性不能被改變,即使想改變的是常量的變數屬性也不行

// 方法二 :另一種替換的方法  self 新建立出來的物件會替換之前的值

struct PointB{
    var x1 = 0.0
    var y1 = 0.0
    mutating func movePointB(x deltaX:Double,y deltaY:Double){
        self = PointB(x1:x1 + deltaX,y1:y1+deltaY)
    }
}

var pointB = PointB(x1:200,y1:200)
print("x=\(pointB.x1),y=\(pointB.y1)")
pointB.movePointB(x: 9, y: 9)
print("x=\(pointB.x1),y=\(pointB.y1)")



筆記地址

相關文章