首页 » 技术分享 » swift学习笔记之拓展和协议

swift学习笔记之拓展和协议

 

/**
*  Protocol(协议)用于统一方法和属性的名称,而不实现任何功能。协议能够被类,枚举,结构体实现,满足协议要求的类,枚举,结构体被称为协议的遵循者。

遵循者需要提供协议指定的成员,如属性,方法,操作符,下标等。
*/
//使用protocol来声明一个协议。

/**
*  协议的语法

协议的定义与类,结构体,枚举的定义非常相似,如下所示:

protocol SomeProtocol {
// 协议内容
}
在类,结构体,枚举的名称后加上协议名称,中间以冒号:分隔即可实现协议;实现多个协议时,各协议之间用逗号,分隔,如下所示:

struct SomeStructure: FirstProtocol, AnotherProtocol {
// 结构体内容
}
当某个类含有父类的同时并实现了协议,应当把父类放在所有的协议之前,如下所示:

class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
// 类的内容
}
*/

protocol ExampleProtocol {
    var simpleDescription: String {
        get
    }
    mutating func adjust()
}

//类,枚举和结构体都可以使用协议。

class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
    simpleDescription += "  Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription

//注意在simpleStructure的声明中关键字mutating的使用,它用来标记这个方法修改了这个结构体。而在simpleClass的声明中则不需要使用mutating,因为类中的方法总是可以被修改的。


//二、协议(protocol)
//可定义方法与属性, 由具体的类去实现. 越来越像Java
//Swift中的协议能被类, 枚举,结构体实现.
protocol SomeProtocol{
    //协议内容
}

class SomeClass : SomeProtocol{ //实现协议, 可实现多个协议

}

//2.1 协议中属性/方法/突变方法的要求
//2.1.1 属性的要求

protocol AnotherProtocol1{
    //class表示类成员(结构体/枚举中用static)
    static var property : Int { get set} //get, set 表示可读可写
}

class AnotherClass1 : AnotherProtocol1{
    class var property : Int {  //实现协议中的属性
        get{
        return 10
        }
        set{

        }
    }
}

//2.1.2 方法要求
//不支持默认参数. 写法上只是没有方法的实现.
protocol AnotherProtocol2{
    func myFunc() -> Int   //只声明不实现
}

class AnotherClass2 : AnotherProtocol2{
    func myFunc() -> Int {  //实现方法
        return 10
    }
}

//2.1.3 突变方法要求
//能在方法或函数内部改变实例类型的方法称为突变方法. (mutating关键字)
//在类中,可以不写mutating, 但在结构体与枚举中国必须写
protocol Togg{
    mutating func togg()
}

enum OnOffSwitch : Togg{
    case Off , On

    mutating func togg() { //改变实例的值
        switch self{
        case .Off:
            self = On
        case .On:
            self = Off
        }
    }
}

var lightSwitch = OnOffSwitch.Off
lightSwitch.togg()   //值变为On

//2.2 协议类型.
//    协议也可以当做类型来使用. 这点和函数一样.
//    1.可作为参数/返回值类型
//2.可作为常量/变量/属性的类型
//3.可作为数组/字典和其他元素类型
protocol MyRect{
    func myLuckNumber() -> Int
}

class MyRectImp : MyRect{
    func myLuckNumber() -> Int {
        return 10
    }
}

class Dice {
    let sides :Int
    var gener : MyRect    //作为类型
    init(sides:Int, gener:MyRect){  //作为参数
        self.sides = sides
        self.gener = gener
    }
}

var dice = Dice(sides: 6, gener: MyRectImp())
dice.gener.myLuckNumber()




//------------------------extention--------------
//使用extension来为已经存在的类型添加功能,就像新的方法和计算属性一样。你可以用extension为已经声明的类型添加协议,甚至是类库中自带的类型。

extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42
    }
}

//使用协议名就像使用其他类型名一样——例如,创建一个不同类型对象的集合,但是这些对象都遵循一个单一的协议。当值的类型是协议类型时,在协议定义以外的方法是不可用的。
//[plain] view plaincopy在CODE上查看代码片派生到我的代码片
let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
//即使protocolValue有一个运行时类型(simpleClass),编译器同样会把它看作是ExampleProtocol类型。也就是说,你不能访问除了遵循协议以外的类的方法和属性。


//一、扩展(extension)
//扩展 extension (类似OC中的分类, 但Swift中没有名字), 即在没有权限获取到原始代码的情况下, 为类增加新功能.
//注意: 只要定义了扩展, 那么该扩展对该类的实例都是可用的.
//extension SomeType{
//    //添加到SomeType的新功能写在这里
//}

//1.1扩展属性(只能是计算属性)
//扩展可以添加新计算属性, 但是不能添加存储属性(也不可以添加属性观察).
extension Double{  //为API中的已有类型添加实例属性
    var km : Double { return self * 1_000.0 }
    var m : Double { return self }
    var cm : Double { return self / 100.0 }
}

let jjLength = 1.m  // 1与m进行点运算, 表示1的Double值
let jjLength_km = 1.km
print(10.km + 1.m)

//1.2扩展构造器
//可以定制自己的构造器
class MyClass{
    var a : Int
    init(){
        a = 10
    }
}

extension MyClass{
    convenience init( parm:Int){   //扩展构造器
        self.init()
        print("扩展构造器--->便利构造器, \(parm)")
    }
}

var myClass = MyClass(parm: 9)

//1.3扩展方法
//下面是像Int中扩展myIntFunc方法
extension Int{
    func myIntFunc(){
        print("值为\(self) , 哈哈哈哈!")
    }
}

1.myIntFunc()

//1.3.1 修改实例方法
//通过扩展方法, 可以修改该实例self本身.但是方法前要加 mutating
extension Double{
    mutating func myMoidfySelfValue() {
        self = self * self //修改self实例的值
    }
}

var d = 2.0
d.myMoidfySelfValue()

//1.4 扩展嵌套类型
//即向已有的嵌套类型中添加新的嵌套类型. 还可以扩展下标(附属脚本)等.
extension Character {
    enum Kind{   //嵌套了一个枚举类型
        case Big
        case Small
    }
    var k : Kind{
        if(String(self).lowercaseString == "a"){
            return Kind.Big
        }else{
            return Kind.Small
        }
    }
}
var ch : Character = "a"
ch.k   //返回一个枚举值Kind.Big

//1.5下标(Subscripts)
//扩展可以向一个已有类型添加新下标。这个例子向Swift内建类型Int添加了一个整型下标。该下标[n]返回十进制数字从右向左数的第n个数字
//123456789[0]返回9
//123456789[1]返回8
//...等等
extension Int {
    subscript(digitIndex: Int) -> Int {
        var decimalBase = 1
        for _ in 1...digitIndex {
            decimalBase *= 10
        }
        return (self / decimalBase) % 10
    }
}
746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7

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

//即等同于:
0746381295[9]

//1.6嵌套类型(Nested Types)
//扩展可以向已有的类、结构体和枚举添加新的嵌套类型:
extension Character {
    enum Kind1 {
        case Vowel, Consonant, Other
    }
    var kind: Kind1 {
        switch String(self).lowercaseString {
        case "a", "e", "i", "o", "u":
            return .Vowel
        case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
        "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
            return .Consonant
        default:
            return .Other
        }
    }
}

//该例子向Character添加了新的嵌套枚举。这个名为Kind的枚举表示特定字符的类型。具体来说,就是表示一个标准的拉丁脚本中的字符是元音还是辅音(不考虑口语和地方变种),或者是其它类型。
//
//这个类子还向Character添加了一个新的计算实例属性,即kind,用来返回合适的Kind枚举成员。
//
//现在,这个嵌套枚举可以和一个Character值联合使用了:
func printLetterKinds(word: String) {
    print("'\\(word)' is made up of the following kinds of letters:")
    for character in word.characters {
        switch character.kind {
        case .Vowel:
            print("vowel ")
        case .Consonant:
            print("consonant ")
        case .Other:
            print("other ")
        }
    }
    print("\n")
}
printLetterKinds("Hello")
// 'Hello' is made up of the following kinds of letters:
// consonant vowel consonant consonant vowel

//函数printLetterKinds的输入是一个String值并对其字符进行迭代。在每次迭代过程中,考虑当前字符的kind计算属性,并打印出合适的类别描述。所以printLetterKinds就可以用来打印一个完整单词中所有字母的类型,正如上述单词"hello"所展示的。
//
//注意:由于已知character.kind是Character.Kind型,所以Character.Kind中的所有成员值都可以使用switch语句里的形式简写,比如使用 .Vowel代替Character.Kind.Vowel

转载自原文链接, 如需删除请联系管理员。

原文链接:swift学习笔记之拓展和协议,转载请注明来源!

0