1. 程式人生 > >[Swift4] Swift筆記 3.0(初探類與物件)

[Swift4] Swift筆記 3.0(初探類與物件)

Swift筆記 3.0

初探類與物件 類,函式,閉包,列舉,結構體

3.1 類定義

類定義 例項化

import Foundation

// 4 類與物件

// 定義 類
 class Shape {
 	var numberOfSides = 0 //成員變數 (屬性)
	 func desicriotion(){  //成員函式 (方法)
		 print("A shape with \(numberOfSides) sides.")
	 }
 }
 
 // 建立類物件,使用
 var s = Shape()
 s.numberOfSides = 6
 s.desicriotion()
 

psswift中 類 和 結構體 的區別

結構體不能被繼承,類可以 他們都能擁有方法

結構體 ---- 值型別 類 ---- 引用型別

//swift中 類 和 結構體 的區別

struct S{
var data : Int = 1
}
var s1 = S()    //結構體物件
var s2 = s1     //呼叫拷貝建構函式物件s2
s2.data = 2
print("\(s1.data),\(s2.data)")
//輸出 1,2


class C{
var data :Int = 1
}
var c1 = C() //類物件
var c2 = c1  //不呼叫拷貝建構函式,增加引用計數
c2.data = 2
print("\(c1.data),\(c2.data)")
//輸出 2,2

3.2 類的 初始化器

入c++,java中的建構函式 或是 構造方法

初始化器 init 來構造 類物件 初始化器沒有返回值 不自定義,會有一個預設初始化器械;若定義了一個就不會有; 反初始化器 (解構函式)deinit 有自帶資源回收機制,一般不考慮析構; ps: 【可選 符號】意思是,初始化可以失敗, 則表示一定會成功

//初始化器  init 來構造 類物件

//命名的類
class NamedShape {
  var numberOfSides = 0
   var name :String

   init(name:String){       //建構函式
  	self.name = name
   }
   deinit {                 //解構函式 絕大情況不需要自己去寫
  	print("Class NamedShape destructed")
   }

  func  simpleDescription() -> String {
  	return "\(name)'s shape with \(numberOfSides) sides"
   }
}

var shapeUnknow = NamedShape(name:"A")
shapeUnknow.numberOfSides = 4
print(shapeUnknow.simpleDescription())
shapeUnknow = NamedShape(name :"new")

3.3 類的屬性

swift中,類有兩種屬性

  1. 儲存屬性
  2. 計算屬性

儲存屬性:又由其為常量或變數(var / let)可分 常量儲存屬性 和 變數儲存屬性,作為例項的一部分,即為普通的屬性,不贅述

計算屬性: 它計算一個值,類似於方法的功能,提供了一個處理資料的入口與出口。其實它更像一個方法,通過一些儲存屬性值的使用,計算出來,但當用戶呼叫時又感覺不到他是方法,使用起來和普通屬性沒有區別,即對使用者透明。 另外: 有 getter stter 需要注意 。

 //舉例: 等邊三角形 ,屬性周長計算屬性
 class EquilaterTriangle{
 	var sideLen :Double   //邊長
 	init (sideLen : Double){
 		self.sideLen = sideLen
	 }
	 
 //計算屬性 ,物件並沒有為計算屬性設定空間,需要時,會用其他屬性計算,但對使用者隱藏了使用如同正常屬性
	 var perimeter: Double { //計算屬性 邊長
		 get { //讀
			 return 3.0 * sideLen
 		}
		 set{ //寫
			 sideLen = newValue/3.0 
			 //跟新 sideLen。 newValue是set的引數
		 }
	 }
 }
 
 var et = EquilaterTriangle(sideLen: 3.1)
 print("\(et.perimeter)")
 et.perimeter = 9.9
 print("\(et.sideLen)")
 

簡化:

如果只讀,則可去掉set,並且可以去掉關鍵字 get 屬性觀察者。監控屬性的變化 willSet —修改之前呼叫 newValue 引數 didSet —修改之後被呼叫 oldValue 引數

//如果只讀,則可去掉set,並且可以去掉關鍵字 get

//屬性觀察者。監控屬性的變化
//willSet ---修改之前呼叫   newValue 引數
//didSet  ---修改之後被呼叫 oldValue 引數

//舉例 :屬性觀察者 觀察變長變化
class  EquilarterTriangle {
    var sideLen :Double = 0.0{
        willSet {
            print("呼叫屬性觀察者willSet ,當前值是 \(sideLen),new value is \(newValue)")
        }
        didSet{
            print("呼叫屬性觀察者didlSet ,當前值是 \(sideLen),old value is \(oldValue)")
        }
    }
}

var et = EquilarterTriangle()
et.sideLen = 10.0
et.sideLen = 20.0

3.4 靜態屬性

//靜態屬性
//儲存與類相關的資料,而不是物件資料 ,比如銀行利率
//static 關鍵字
//形成 類的屬性,類的方法,即該類物件共有
//可以由類名 直接使用,不用建立物件

下標

建立下標,直接用下標去訪問屬性

//下標 subscrip
//舉例: 使用三角形 下標 返回三角形三邊的長度

class Triangle {
    var sideLen1: Double
    var sideLen2: Double
    var sideLen3: Double
    init(sideLen1 :Double ,sideLen2 :Double , sideLen3 :Double) {
        self.sideLen1 = sideLen1
        self.sideLen2 = sideLen2
        self.sideLen3 = sideLen3
    }
    subscript(sideIndex: Int)->Double{
        switch sideIndex{
        case 1: return sideLen1
        case 2: return sideLen2
        case 3: return sideLen3
        default : return -1
        }
    }
}

var T1 = Triangle(sideLen1: 3.0, sideLen2: 4.0, sideLen3: 5.0)

print(T1[1])
print(T1[2])
print(T1[3])
print(T1[4])

3.5 繼承

正如所有面向物件程式設計思想,繼承是為了解決程式碼重複編寫 如經典例子: 一個 Cat 類 一個 Dog 類 一個 Frog 類… 可能他們都有 屬性:age (年齡) 方法:eat(進食); sleep(睡覺) 那麼沒增加定義一個相似的類,只有重新寫一遍相關程式碼。

這不符合 Smart and Lazy 原則,所以採用 程式碼 Reuse【複用】的基本思路。 我們構造一個 Animal 類,其他的類就好像如同這個類所衍生而來,這個Animal類如同父親一般,我們把它叫做父類,或是超類。而派生而來的叫,派生類或子類。子類直接擁有父類的屬性和方法。就如同繼承一般。

繼承 swift特點

  1. 類可以繼承其他的類 ,把父親類的資料和方法都構造出來
  2. “:”表示 繼承 關鍵符 ,前為子類 ,後為父類
  3. 不需要標準類根
  4. 子類重寫父類 方法,只需要用 關鍵字 【override】標記
  5. 單繼承,只能有一個父類
//繼承
子類繼承時構造順序必須是:
//構造器 init 執行三步
//1.設定子類宣告的屬性值
//2.呼叫父類的構造器
//3.改變父類的屬性值,其他工作如呼叫方法,修改父類方法在此過程


//實現一個正方形的類,繼承了形狀【nameShape】類
//重寫simpleDescription 方法

class Square : NamedShape {
    var sideLen : Double
    init (sideLen:Double,name:String){
        self.sideLen = sideLen //初始化子類的屬性
        super.init(name: name) //初始化父類屬性,使用父類的建構函式
        numberOfSides = 4      //修改父類的屬性
        // 順序很重要
    }
    func area() -> Double {
        return sideLen*sideLen
    }
    override func simpleDescription() -> String {  //overrie 關鍵字 重寫 父類的方法
        return "A square with side Length \(sideLen) ."
    }
}

let square = Square(sideLen: 2.0, name: "C")
print(square.area())
print(square.simpleDescription())

//便利初始化
class ClassA{
    let num :Int
    init(num:Int){
        self.num = num
    }
    convenience init(bigNum:Bool)//便利初始化器,呼叫初始化器,必須呼叫指定的構造器
    {
        self.init(num : bigNum ? 10000 : 1)
    }
}
var objA = ClassA(bigNum: true)
print(objA.num)
//required 關鍵字
//子類有其他初始化器的時候,必須重寫

class C {
    var num: Int
    required init(num :Int){ //子類有其他初始化器的時候,必須重寫
        self.num = num
    }
}
class D : C {
    let numD :Int
    let str :String
    init(str:String, num :Int) {
        self.str = str
        self.numD = num
        super.init(num: num)
    }
    
    required init(num: Int) {
        self.numD = num + 2
        self.str = "Hello"
        super.init(num: num)
    }
}

let objD = D(str: "FIFA", num: 20)
//其他一些知識點

//final
//類 則 不能繼承
//屬性方法 則 不能修改


//is 是否是某一個型別
//as

//Any 任何class的型別

//AnyObject 任何型別 (除了方法型別,函式型別)


//理解型別的判斷
class Human{}
class Man : Human{}
class Woman :Human{}
let man = Man()
let woman = Woman()
var arr = [ man , woman ]
for people in arr{
    if people is Man{
        print("This is Man")
    }
    if people is Woman{
        print("THis is Woman")
    }
}

一個綜合的例子;

// 綜合例子:
enum Sex {
    case female
    case male
}
class Person{
    var firstName: String
    var lastName: String
    var age: Int
    
    var gender :Sex
    var fullName: String  { //計算屬性
        return firstName+lastName
    }
    
    required init(firstName:String,lastName:String,age:Int,gender:Sex) {
        self.age=age
        self.firstName=firstName
        self.lastName=lastName
        self.gender=gender
    }
    convenience init(defaultData:Bool)//便利初始化器,呼叫初始化器,必須呼叫指定的構造器
    {
        self.init(firstName: "Jack", lastName: "Smith", age: 20, gender: Sex.male )
    }
    
    func work()  {
        print("Person \(fullName) is working.")
    }
    
}

class Student: Person {
    /*var sideLen : Double
    init (sideLen:Double,name:String){
        self.sideLen = sideLen //初始化子類的屬性
        super.init(name: name) //初始化父類屬性,使用父類的建構函式
        numberOfSides = 4      //修改父類的屬性
        // 順序很重要
    }*/
    var StuID : String
    var cScore :Int
    var cppSore :Int
    var dataStruct : Int
    init(StuID : String,cScore :Int,cppSore :Int,dataStruct : Int,firstName:String,lastName:String,age:Int,gender:Sex) {
        self.cppSore=cppSore
        self.cScore=cScore
        self.dataStruct = dataStruct
        self.StuID =  StuID
        super.init(firstName:firstName , lastName: lastName, age: age, gender: gender)
    }
   
    
    required init(firstName: String, lastName: String, age: Int, gender: Sex) {
        fatalError("init(firstName:lastName:age:gender:) has not been implemented")
    }
    subscript(sideIndex: Int)->Int{
        switch sideIndex{
        case 1: return cScore
        case 2: return cppSore
        case 3: return dataStruct
        default : return -1
        }
    }
    
}
class Teacher: Person {
    
 override func work() {
 print("Student \(fullName) is Learning.")
 }
}


var person1 = Person(defaultData: true)
var teacherForIOS = Teacher(firstName: "Doctor", lastName: "Who", age: 40, gender: Sex.male)
var student1 = Student(StuID: "2016110246", cScore: 90, cppSore: 95, dataStruct: 55, firstName: "張", lastName:"飛", age: 20, gender: Sex.male)

person1.work()
teacherForIOS.work()
student1.work()
print(student1[1])
print(student1[2])
print(student1[3])

僅為筆記 , 旨在記錄,定有缺漏,有錯必改