//***********swift学习之27--扩展--***************************
/*
 扩展跟OC一样就是向一个已有的类、结构体或枚举类型添加新功能。
 只能添加新的功能,不能重写已有的功能。
 */

// 扩展声明使用关键字 extension:
// 一个扩展可以扩展一个已有类型,使其能够适配一个或多个协议,语法格式如下:
// extension SomeType: SomeProtocol, AnotherProctocol {
     // 协议实现写到这里
// }


// Swift 中的扩展可以:
// 1.添加计算型属性和计算型静态属性
// 2.定义实例方法和类型方法
// 3.提供新的构造器
// 4.定义下标
// 5.定义和使用新的嵌套类型
// 6.使一个已有类型符合某个协议

// 1.添加计算型属性
// 下面的例子向 Int 类型添加了 4 个计算型实例属性并扩展其功能:
extension Int {
    var add: Int {return self + 100 }
    var sub: Int { return self - 10 }
    var mul: Int { return self * 10 }
    var div: Int { return self / 5 }
}

let addition = 3.add
print("加法运算后的值:\(addition)")

let subtraction = 120.sub
print("减法运算后的值:\(subtraction)")

let multiplication = 39.mul
print("乘法运算后的值:\(multiplication)")

let division = 55.div
print("除法运算后的值: \(division)")

let mix = 30.add + 34.sub
print("混合运算结果:\(mix)")




// 2方法
// 扩展可以向已有类型添加新的实例方法和类型方法。
// 下面的例子向Int类型添加一个名为 topics 的新实例方法:
extension Int {
    func topics(summation: () -> ()) {
        for _ in 0..<self {
            summation()
        }
    }
}

4.topics(summation: {
    print("扩展模块内")
})

3.topics(summation: {
    print("内型转换模块内")
})

// 2.可变实例方法
/*
 通过扩展添加的实例方法也可以修改该实例本身。
 结构体和枚举类型中修改self或其属性的方法必须将该实例方法标注为mutating,正如来自原始实现的修改方法一样。
 实例
 下面的例子向 Swift 的 Double 类型添加了一个新的名为 square 的修改方法,来实现一个原始值的平方计算:
 */

extension Double {
    mutating func square() {
        let pi = 3.1415
        self = pi * self * self
    }
}

var Trial1 = 10.0
Trial1.square()
print("圆的面积为: \(Trial1)")


var Trial2 = 1.0
Trial2.square()
print("圆的面积为: \(Trial2)")


var Trial3 = 2.0
Trial3.square()
print("圆的面积为: \(Trial3)")


// 3.构造器
// 扩展可以向已有类型添加新的构造器。
// 这可以让你扩展其它类型,将你自己的定制类型作为构造器参数,或者提供该类型的原始实现中没有包含的额外初始化选项。
// 扩展可以向类中添加新的--便利构造器 init()--,但不能向类中添加新的指定构造器或析构函数 deinit() 。
struct sum {
    var num1 = 100, num2 = 200
}

struct diff {
    var no1 = 200, no2 = 100
}

struct mult {
    var a = sum()
    var b = diff()
}

let calc = mult()
print ("mult 模块内 \(calc.a.num1, calc.a.num2)")
print("mult 模块内 \(calc.b.no1, calc.b.no2)")

let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))

print("mult 模块内 \(memcalc.a.num1, memcalc.a.num2)")
print("mult 模块内 \(memcalc.b.no1, memcalc.b.no2)")

extension mult {
     // 有时候我们并不关心区间内每一项的值,能够使用下划线来忽略这些值。
    init(x: sum, y: diff) {
        _ = x.num1 + x.num2
        _ = y.no1 + y.no2
    }
}


let a = sum(num1: 100, num2: 200)
print("Sum 模块内:\( a.num1, a.num2)")


let b = diff(no1: 200, no2: 100)
print("Diff 模块内: \(b.no1, b.no2)")

let calcee = mult(x:a,y:b)




// 4.下标
// 扩展可以向一个已有类型添加新下标。
// 以下例子向 Swift 内建类型Int添加了一个整型下标。该下标[n]返回十进制数字
extension Int {
    subscript( multtable: Int) -> Int {
        var multtable = multtable
        var no1 = 1
        while multtable > 0 {
            no1 *= 10
            multtable -= 1
        }
        return (self / no1) % 10
    }
}

print("4.下标---\(12[0])")
print("4.下标---\(7869[1])")
print("4.下标---\(786543[2])")


// 5.嵌套类型
// 扩展可以向已有的类、结构体和枚举添加新的嵌套类型:
extension Int {
     //扩展了一个枚举
    enum calc
    {
        case add
        case sub
        case mult
        case div
        case anything
    }
    
    // 扩展了一个闭包
    var printCase: calc {
        switch self
        {
        case 0:
            return .add
        case 1:
            return .sub
        case 2:
            return .mult
        case 3:
            return .div
        default:
            return .anything
        }
    }
}

func result(numb: [Int]) {
    for i in numb {
        switch i.printCase {
        case .add:
            print(" 10 ")
        case .sub:
            print(" 20 ")
        case .mult:
            print(" 30 ")
        case .div:
            print(" 40 ")
        default:
            print(" 50 ")
            
        }
    }
}

result(numb: [0, 1, 2, 3, 4, 7])