iOS --- 扩展和泛型(swift2.3)

iOS — 扩展和泛型(swift)

下面简单的介绍扩展和泛型的应用

  1. 扩展基础

  2. 嵌套类型

  3. 扩展标准库

  4. 泛型函数

  5. 泛型类型


一:扩展基础

struct Point{
    var x = 0.0
    var y = 0.0
}

struct Size{
    var width = 0.0
    var height = 0.0
}

class Rectangle{

    var origin = Point()
    var size = Size()

    init( origin: Point , size: Size ){
        self.origin = origin
        self.size   = size
    }
}


// extension 中放入新的方法
extension Rectangle{//类的扩展中只能扩展方法,计算型属性和convenience的init方法,而类型的存储属性和init方法只能写在类中,这就是扩展,帮助开发者实现多人开发

    // 如果是struct,就需要使用mutating关键字
    func translate(x x: Double, y: Double){

        self.origin.x += x
        self.origin.y += y
    }
}


let rect = Rectangle(origin: Point(), size: Size(width: 4, height: 3))
rect.translate(x: 10, y: 10)
rect


// extension 中放入新的属性
extension Rectangle{

    // extension中只能放入计算型属性
    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 area: Double{
        return size.width * size.height
    }

    var perimeter: Double{
        return 2*(size.width + size.height)
    }


    // 可以在extension中根据计算性属性放入新的构造函数
    // extension中只能放入convenience的构造函数
    convenience init(center: Point, size: Size){
        let originX = center.x - size.width/2
        let originY = center.y - size.height/2
        //self.origin = Point(x: originX, y: originY)
        //self.size = size
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}


rect.area
rect.perimeter
rect

let rect2 = Rectangle(center: Point(), size: Size(width: 6, height: 8))
rect2
二:嵌套类型
//nested type
class UI{

    enum Theme{
        case DayMode
        case NightMode
    }

    var fontColor: UIColor!
    var backgroundColor: UIColor!
    var themeMode: Theme = .DayMode{
        didSet{
            self.changeTheme(self.themeMode)
        }
    }

    init(){
        self.themeMode = .DayMode
        self.changeTheme(self.themeMode)

    }

    init(themeMode: Theme){
        self.themeMode = themeMode
        self.changeTheme(themeMode)
    }

    func changeTheme( themeMode: Theme ){
        switch(themeMode){
        case .DayMode:
            fontColor = UIColor.blackColor()
            backgroundColor = UIColor.whiteColor()
        case .NightMode:
            fontColor = UIColor.whiteColor()
            backgroundColor = UIColor.blackColor()
        }
    }
}


let ui = UI()
ui.themeMode
ui.fontColor
ui.backgroundColor

ui.themeMode = .NightMode
ui.themeMode
ui.fontColor
ui.backgroundColor


// 以前就见过Nest Type这个就是一个嵌套的枚举类型,Index就是定义在string类里面的类型
// String.Index
let str = "Hello World"
let index = str.startIndex.advancedBy(5)
str.substringToIndex(index)


//
struct Point{
    var x = 0.0
    var y = 0.0
}

struct Size{
    var width = 0.0
    var height = 0.0
}

class Rectangle{

    var origin = Point()
    var size = Size()

    init( origin: Point , size: Size ){
        self.origin = origin
        self.size   = size
    }
}

// extension 中放入 Nested Type, Methods 和 subscript
extension Rectangle{

    // extension 中放入 Nested Type
    enum Vertex: Int{
        case LeftTop
        case RightTop
        case RightBottom
        case LeftBottom
    }

    func pointAtVertex( v: Vertex ) -> Point{

        switch v{
        case .LeftTop:
            return origin
        case .RightTop:
            return Point(x: origin.x + size.width, y: origin.y )
        case .RightBottom:
            return Point(x: origin.x + size.width, y: origin.y + size.height )
        case .LeftBottom:
            return Point(x: origin.x, y: origin.y + size.height )
        }
    }

    // extension 中放入 subscript
    subscript(index: Int) -> Point{
        //assert的功能在于:如果index参数不满足条件,那么就会打印出Index in Rectange Out of Range.
        assert( index >= 0 && index < 4 , "Index in Rectange Out of Range.")
        return pointAtVertex(Vertex(rawValue: index)!)
    }
}


let rect = Rectangle(origin: Point(), size: Size(width: 4, height: 3))
rect.pointAtVertex(.RightBottom)

rect[0]
rect[1]
rect[2]
rect[3]

三:扩展标准库
extension Int{

    var square: Int{//扩充标准库的计算属性
        return self*self
    }

    var cube: Int{
        return self*self*self
    }

    //扩充方法
    func inRange(closedLeft left: Int, openedRight: Int) -> Bool{
        return self >= left && self < openedRight
    }

    //这里的参数的类型是个函数
    func repetitions(task: () -> Void ){
        for _ in 0..<self{
            task()
        }
    }

    func stride(to end: Int, by stride: Int, task: (Int) -> Void ){

        for i in self.stride(to: end, by: stride){
            task(i)
        }
    }
}

let num = 8
num.square

let str = "Hello, Swift"
let index = 21
index.inRange(closedLeft: 0, openedRight: str.characters.count)

10.repetitions{
    print("Hello, Swift")
}

for i in 2.stride(to: 10, by: 2){
    print(i)
}

for i in 2.stride(through: 10, by: 2){
    print(i)
}

2.stride(to: 10, by: 2){ num in
    print(num*num)
}


// Int还有很多可以做enxtension的地方
// 如 12345[2]
// 如 toBinary, toHex
// 如 isPrime


// extension在App开发中被经常使用
// 如 String, UIColor等基础类的使用


// 在App开发中, 一个界面可能需要处理多个事件: 表格显示, 用户输入, 导航, 动画, 数据存储...
// 此时可以使用extension分隔开
四:泛型函数
func swapTwoInt(inout a: Int , inout _ b: Int){//这里的inout关键字表面:参数的传递是按照引用传递的
    (a,b) = (b,a)
}

var a: Int = 0
var b: Int = 6
swapTwoInt(&a, &b)
a
b

func swapTwoDouble(inout a: Double , inout _ b: Double){
    (a,b) = (b,a)
}


// 使用generic
// generic function(泛型函数):前面两个函数的意思其实是一样的,就是交换两个参数的值,只是类型不一样,这样做产生了冗余的代码,下面这个swapTwoThings函数为我们引出了泛型的概念,<T>:表示这个函数的参数的类型是T,那么无论我们传入的是int类型的参数还是string类型,只要定义了这个泛型函数的逻辑,传入参数的任意类型都能使用这个逻辑,扩展了函数的通用性
func swapTwoThings<T>(inout a: T , inout _ b: T){
    (a,b) = (b,a)
}

var hello = "Hello"
var bye = "Bye"
swapTwoThings(&hello, &bye)
hello
bye

swapTwoThings(&a, &b)
a
b

swap(&a, &b)

五:泛型类型
// generic type
let arr = Array<Int>()
let dict = Dictionary<String,Int>()
let set  = Set<Float>()
//注意:一个空数组的声明有两种写法,利用inference可以知道aaa和b的数据类型是个数组
let aaa = [Int]()
let b = Array<Int>()


struct Stack<T>{//<T>表示stack里面的数据类型是任意的

    var items = [T]()//在这里声明一个T类型的数组

//    //当然声明一个空数组也可以这样写:
//    var items1:Array<T> = [T]()
//    
//    //或者这么写
//    var items2:Array<T> = Array<T>()



    func isEmpty() -> Bool{//返回值为bool类型的函数,用来判断数组是否为空
        return items.count == 0
    }

    mutating func push(item: T){//由于stack是一个结构体,这个push函数改变了结构体中的数据,那么应该使用mutating关键字
        items.append(item)
    }

    mutating func pop() -> T?{

        guard !self.isEmpty() else{
            return nil
        }

        return items.removeLast()
    }

}

extension Stack{

    func top() -> T?{
        return items.last
    }

    func count() -> Int{
        return items.count
    }
}


var s = Stack<Int>()
s.push(1)
s.push(2)
s.pop()

var ss = Stack<String>()


struct Pair<T1,T2>{//通过字典引出结构体中可以拥有两个泛型的数据类型

    var a: T1
    var b: T2

}

var pair = Pair<Int,String>(a: 0 , b: "Hello")
pair.a
pair.b
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值