swift簡單總結(四)—— 函數和類

版本記錄

版本號 時間
V1.0 2017.07.18

前言

我是swift2.0的時候開始接觸的,記得那時候還不是很穩定,公司的項目也都是用oc做的,并不對swift很重視,我自己學了一段時間,到現在swift3.0+已經出來了,自己平時也不寫,忘記的也差不多了,正好項目這段時間已經上線了,不是很忙,我就可以每天總結一點了,希望對自己對大家有所幫助。在總結的時候我會對比oc進行說明,有代碼的我會給出相關比對代碼。
1. swift簡單總結(一)—— 數據簡單值和類型轉換
2. swift簡單總結(二)—— 簡單值和控制流
3. swift簡單總結(三)—— 循環控制和函數

函數

1. 函數作為參數傳入另一個函數

前面在講函數的時候,我們看到函數是可以嵌套的,還可以作為返回值返回,這里我們講另外一種情況,那就是函數作為參數進行傳遞,也就是說,函數的參數是另外一個參數。

下面我們就看一下 swift中的代碼。

    override func viewDidLoad()
    {
        super.viewDidLoad()
   
        view.backgroundColor = UIColor.lightGray

        //函數作為參數進行傳遞
        let numbers = [20, 15, 18, 9]
        let matchCondition = match(list: numbers, condition: lessThan)
        print(matchCondition)
    }

    //函數作為參數進行傳遞
    func match(list : [Int], condition:(Int) -> Bool) -> Bool {
        for item in list {
            if condition(item) {
                return true
            }
        }
        return false;
    }
    
    func lessThan(number : Int) -> Bool {
        return number < 18
    }

2. 函數的本質

函數的本質其實就是一種特殊的閉包,可以使用{}來創建一個匿名閉包,使用in將參數和返回值類型聲明與閉包函數體進行分離。

    //函數實質上就是閉包
    numbers.map({
    (number : Int) -> Int in
        let result = number * 3
        return result
    })

如果一個閉包的類型已知,比如作為一個回調函數,你可以忽略參數的類型和返回值,單個語句閉包會把它語句的值單做結果返回。


let  mappedNumbers =  numbers.map({number in 3 * number})

可以通過參數位置而不是參數名字來引用參數,這個方法在非常短的閉包中非常有用,當一個閉包作為最后一個參數傳給一個函數的時候,它可以直接跟在括號后面。

let sortNumbers = sorted(numbers) {$0 > $1}


1. 類的創建

使用class和類名創建一個類,類中屬性的聲明和常量、變量聲明一樣,唯一的區別是它們的上下文是類,同樣,方法和函數聲明也一樣。

下面看一下代碼

class name{
    var number = 0
    
    func myname() -> String {
       return "John"
    }
}

要創建一個類的實例,在類名后面加上括號,使用點語法來訪問實例的屬性和方法。

class JJSwiftVC: UIViewController
{

    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.lightGray

        //類實例化
        var nameInstance = name()
        nameInstance.number = 10
        var nameFunc = nameInstance.myname()
        print(nameFunc)
    }
}

下面我們就直接看輸出

John

2. 構造器

一個構造函數來初始化實例,使用init來創建一個構造器。

下面看代碼。

class NamedShape{
    var numberOfSlides : Int = 0
    var name : String
    
    init(name : String) {
        self.name = name
    }
    
    func simpleDescription() -> String {
        return "A shape with \(numberOfSlides) sides."
    }
}

這里self被用來區別實例變量,當你創建實例的時候,像傳入參數一樣給類傳入構造器參數,每個屬性都需要賦值——無論是通過聲明(就像numberOfSlides)或者是通過構造器(就像name)。

如果你需要在刪除對象之前進行一些清理工作,使用deinit創建一個析構函數。

3. 子類的定義

子類的定義就是在其類名后面加上父類的名字,用冒號分割,創建類的時候并不需要一個標準的根類,所以可以忽略父類。

我們先看一下swift中是如何定義子類的,看代碼。

class JJSwiftVC: UIViewController
{

}

上面就是定義了一個子類JJSwiftVC,再比如

class name{
    var number = 0
    
    func myname() -> String {
       return "John"
    }
}

這個類就沒有指定父類。

那么我們在看一下oc中子類的定義,看代碼。

#import <UIKit/UIKit.h>

@interface JJOCVC : UIViewController

@end

我們可以得到如下結論:

  • oc和swift子類和父類之間都是以冒號隔開。
  • oc中繼承父類是寫在.h文件中,swift則不分文件。
  • oc在新建文件的時候就要指定父類,且不能省略,swift可以不知道根類。

4.子類重寫父類的方法

swiftoc一樣,子類可以重寫父類的方法,swift中子類要重寫父類的方法,需要用override標記,沒有這個標志就重寫父類方法會報錯,下面我們就看一下代碼。

class NamedShape
{
    var numberOfSlides : Int = 0
    var name : String
    
    init(name : String) {
        self.name = name
    }
    
    func simpleDescription() -> String {
        return "A shape with \(numberOfSlides) sides."
    }

}

class Square : NamedShape
{

    override func simpleDescription() -> String {
        return "子類在重寫父類方法"
    }
}

下面我們看一下oc中是如何重寫父類方法的。

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor lightGrayColor];
    
    self.imageArr = [self loadGifImageArr];
    
    [self setupUI];
}

這就是典型的重寫父類的方法,不用任何標志,直接在子類里實現父類的方法就是相當于重寫父類的方法了。

5. 屬性的getter&setter方法

下面我們看一下swift中的settergetter方法,看代碼。

class JJSwiftVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.lightGray
 
                let triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
        print(triangle.permeter)
        triangle.permeter = 9.9
        print(triangle.sideLength)
    }
}

class EquilateralTriangle : NamedShape
{
    var sideLength : Double = 0.0
    
    init(sideLength : Double, name : String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSlides = 3
    }
    
    var permeter : Double{
        get {
        
            return 3.0 * sideLength
        }
        set{
        
            sideLength = newValue / 3.0
        }
    }
    
    override func simpleDescription() -> String {
        return "An equilateral Triangle with sides of lenght \(sideLength)"
    }

}

下面我們看結果輸出。

9.3
3.3

上面的不難理解,getter方法是3.0 * sideLength,3.1 * 3 = 9.3,后面的setter方法是新值9.9 / 3 = 3.3。

這里,類EquilateralTriangle的構造器,需要執行三步:

  • 設置子類聲明的屬性值
  • 調用父類的構造器
  • 改變父類定義的屬性值,其他的工作比如調用方法,getter和setter也可以在這個階段完成。

如果不需要計算屬性,但是仍然需要在設置一個新值之前或者之后運行代碼。可以使用willSetdidSet

下面我們看一下代碼。

class JJSwiftVC: UIViewController
{

    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.lightGray

        let triangleAndSqure = TriangleAndSquare(size : 10, name : "another test shape")
        print(triangleAndSqure.square.sideLength)
        print(triangleAndSqure.triangle.sideLength)
        triangleAndSqure.square = Square(sideLength: 50, name: "larger square")
    }
}

class TriangleAndSquare
{
    var triangle : EquilateralTriangle{
        willSet {
        
            square.sideLength = newValue.sideLength
        }
    
    }
    
    var square : Square{
        willSet {
            
            triangle.sideLength = newValue.sideLength
        }
    }
    
    init(size : Double, name : String) {
        square = Square(sideLength : size, name : name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
}

上面的就是swift中的getter和setter方法,不知道大家是否記得oc中的getter和setter方法。

  • oc中的getter方法用點語法就可以點出來。
  • oc中的setter方法也可以使用點語法進行賦值。
  • oc中的getter和setter方法都可以重寫。

6. 類中的方法和函數

類中的方法和函數有一個重要的區別,函數的參數名只能在函數內部使用,但是方法的參數名需要在調用的時候顯示說明(除了第一個參數),默認情況下,方法的參數名和它在方法內部的名字一樣,不過你可以定義第二個名字,這個名字被用在方法內部,下面看代碼。

class JJSwiftVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.lightGray
        var counter = Counter()
        counter.incrementBy(2, numberOfTimes: 7)
        
    }
}

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

下面看輸出結果

14

這里可見:

  • 這里times就是給numberOfTimes起的別名。

還需要說明的是,在操作可選值的時候,在操作之前加上?,如果?之前是nil?后面的東西都會被忽略,并且整個表達式會返回nil,否則,?之后的東西都會被運行,在這兩種情況下,整個表達式的值是一個可選值。

下面我們看一下代碼。

let optionalSquare : Square? = Square(sideLength : 2.5, name : "optional square")

let sideLength = optionalSquare. sideLength

后記

已經很晚了,今天就寫這么多吧,未完,待續~~~

sea
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容