swift学习- 扩展(二十一)

来源:互联网 发布:淘宝刚上架过期不存在 编辑:程序博客网 时间:2024/04/29 18:23


/*扩展就是向一个已有的类、结构体、枚举类型或者协议类型添加新功能(functionality)。

这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。扩展和 Objective-C中的分类(categories)类似。

(不过与 Objective-C不同的是,Swift 的扩展没有名字。)


Swift 中的扩展可以:


添加计算型属性和计算型静态属性

定义实例方法和类型方法

提供新的构造器

定义下标

定义和使用新的嵌套类型

使一个已有类型符合某个协议

Swift 中,你甚至可以对一个协议(Protocol)进行扩展,提供协议需要的实现,或者添加额外的功能能够对合适的类型带来额外的好处。

你可以从协议扩展获取更多的细节。


注意:

扩展可以添加新的计算属性,但是不可以添加存储属性,也不可以向已有属性添加属性观测器(property observers)

扩展可以对一个类型添加新的功能,但是不能重写已有的功能。

如果你使用扩展提供了一个新的构造器,你依旧有责任保证构造过程能够让所有实例完全初始化。


扩展语法(Extension Syntax

声明一个扩展使用关键字extension


extension SomeType {

// 加到SomeType的新功能写到这里

}

一个扩展可以扩展一个已有类型,使其能够适配一个或多个协议(protocol)。当这种情况发生时,

协议的名字应该完全按照类或结构体的名字的方式进行书写:


extension SomeType: SomeProtocol, AnotherProctocol {

// 协议实现写到这里

}

按照这种方式添加的协议遵循者(protocol conformance)被称之为在扩展中添加协议遵循者


注意:

如果你定义了一个扩展向一个已有类型添加新功能,那么这个新功能对该类型的所有已有实例中都是可用的,

即使它们是在你的这个扩展的前面定义的。

*/


//扩展Double,添加计算型属性

extension Double {

    var km: Double {return self *1_000.0 }

    var m: Double {return self }

    var cm: Double {return self /100.0 }

    var mm: Double {return self  /1_000.0 }

    var ft: Double {return self /3.28084 }

}

//可以用点语法访问

let oneInch = 25.4 .mm

print("One inch is\(oneInch) meters")

//One inch is 0.0254 meters

let threeFeet = 3.ft

print("Three feet is\(threeFeet) meters")

//Three feet is 0.914399970739201 meters


//应为只读计算属性返回Double值,可以用于值计算

let aMarathon = 42.km +195.m

print("A marathon is\(aMarathon) meters long")

//A marathon is 42195.0 meters long


/*扩展可以向已有类型添加新的构造器。这可以让你扩展其它类型,将你自己的定制类型作为构造器参数,

或者提供该类型的原始实现中没有包含的额外初始化选项。


扩展能向类中添加新的便利构造器,但是它们不能向类中添加新的指定构造器或析构器。指定构造器和析构器必须总是由原始的类实现来提供。

*/

struct Size {

    var width = 0.0, height =0.0

}

struct Point {

    var x = 0.0, y =0.0

}

struct Rect {

    var origin = Point()

    var size = Size()

    

}

let defaultRect = Rect()

let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))

/*如果你使用扩展向一个值类型添加一个构造器,在该值类型已经向所有的存储属性提供默认值,而且没有定义任何定制构造器(custom initializers)时,你可以在值类型的扩展构造器中调用默认构造器(default initializers)和逐一成员构造器(memberwise initializers)

*/

extension Rect {

    init(center: Point, size:Size) {

        let originX = center.x - size.width /2

        let originY = center.y - size.height /2

        self.init(origin:Point(x: originX, y: originY), size: size)

    }

    func prints() {

        print("origin: (\(origin.x),\(origin.y)), size: (\(size.width),\(size.height))")

    }

}

let centerRect = Rect(center:Point(x: 4.0, y:4.0), size: Size(width:3.0, height: 3.0))


//一担扩展Rect添加新功能,前面定义的实例memberwiseRect也可以访问新的功能

memberwiseRect.prints();

//origin: (2.0,2.0), size: (5.0, 5.0)

centerRect.prints();

//origin: (2.5,2.5), size: (3.0, 3.0)


//值个值类型Point提供了一个定制构造器

struct Point1 {

    var x:Double, y:Double

    init(x:Double, y:Double, des:String) {

        self.x = x

        self.y = y

        print("\(des): x:\(x), y:\(y)")

    }

}

//p1 不能狗访问Point1的默认成员构造器

var pt1 = Point1(x:2.0, y: 3.0, des:"传入的参数是")

//传入的参数是: x:2.0, y:3.0

extension Point1 {

    

    init(x:Double, y:Double, des:String, count: Double) {

        //同里这里也不能访问Point1的默认成员构造器

        self.init(x: x, y: y, des: des)

        print("和是:\(count)")

    }

}

var exPt1 = Point1(x:2.0, y: 3.0, des:"传入的参数是", count:5.0)

//传入的参数是: x:2.0, y:3.0

//和是:5.0

class Student {

    var name:String, sex:String

    init(name: String, sex:String) {

        self.name = name

        self.sex = sex

    }

}

//扩张类的构造器的时候必须写成便利构造器,不然会报错

extension Student {

    convenience init(name:String, sex:String, school:String) {

        self.init(name: name, sex: sex)

    }

}

//扩展可以向已有类型添加新的实例方法和类型方法。下面的例子向Int类型添加一个名为repetitions的新实例方法:

extension Int {

    func repetitions(task: () -> ()) {

        for _in 0..<self {

            task()

        }

    }

}

//Int值调用

3.repetitions({print("Hello")})

//Hello

//Hello

//Hello


//使用尾随闭包

3.repetitions{

    print("GoodBye")

}

//GoodBye

//GoodBye

//GoodBye


//通过扩展添加的实例方法也可以修改该实例本身。Int为值类型,修改实例的方法必须加上mutating

extension Int {

    mutating func square() {

        self = self *self

    }

}

var someInt = 3

someInt.square();

print(someInt)//9

/*扩展可以向一个已有类型添加新下标。这个例子向Swift内建类型Int添加了一个整型下标。

该下标[n]返回十进制数字从右向左数的第n个数字


123456789[0]返回9

123456789[1]返回8

...等等

*/

extension Int {

    subscript(var digitIndex:Int) -> Int {

        var decimalBase = 1

        while digitIndex > 0 {

            decimalBase *= 10

            --digitIndex

        }

        return (self / decimalBase) %10

    }

}

print(746381295[0])//5

print(746381295[1])//9

//如果该Int值没有足够的位数,即下标越界,那么上述实现的下标会返回0,因为它会在数字左边自动补0

print(746381295[9])//0


//扩展可以向已有的类、结构体和枚举添加新的嵌套类型:

extension Int {

    enum Kind {

        case Negative, Zero, Positive

    }

    var kind: Kind {

        switch self {

        case 0:

            return .Zero

        case let xwhere x > 0:

            return .Positive

        default:

            return .Negative

        }

    }

}

func printIngegerKinds(numbers: [Int]) {

    for number in numbers {

        switch number.kind {

        case .Negative:

            //加入terminator:""不让换行

            print("- ", terminator:"")

        case .Zero:

            print("0 ", terminator:"")

        case .Positive:

            print("+ ", terminator:"")

        }

    }

    print("")

}


printIngegerKinds([3,19,-27,-5,0,6])

//+ + - - 0 +

0 0