
协议定义了一个方法的蓝图,属性和其他适合特定任务或功能的要求。协议实际上并不提供一个这些要求的实现,它只是描述了一个实现会是什么样子。协议可以通过一个类,结构或枚举提供这些要求的具体实现。满足要求的任何类型的协议都是符合协议。
协议可以要求符合类型有特定的实例属性,实例方法,类型丰富, *** 作符和下标。
1. 协议的语法协议名放在类型名之后,用冒号分割,当作定义的一部分。可以列出多个协议,由逗号分隔。
如果一个类有父类,在任何协议之前列出父类名,后跟一个逗号。
protocol FirstProtocol { // protocol deFinition goes here}protocol AnotherProtocol { // protocol deFinition goes here}class SomeSuperclass{}class SomeClass: SomeSuperclass,FirstProtocol,AnotherProtocol { // protocol deFinition goes here} 2. 属性要求 属性要求总是声明为变量属性,用var关键字做前缀。可获取和可设置属性是通过在他们类型声明后编写{ get set }方法,并且可获取属性是通过编写{ get }方法。
协议例子如下:
protocol ExampleProtocol { var simpleDescription: String { get } //在协议中定义方法时需要注意,类中的方法因为本身就可以改变类不需要mutating关键字修饰,但是结构struct和枚举enum使用协议时,协议和struct,enum都需要在定义和使用方法前用mutating关键字修饰 mutating func adjust()} 2.1 结构struct使用协议 //结构体使用协议struct SimpleStructure: ExampleProtocol { var simpleDescription: String = "A simple " mutating func adjust() { simpleDescription += "struct." }}var b = SimpleStructure()b.adjust()let bDescription = b.simpleDescriptionprint(bDescription) //"A simple struct.\n"//结构体重的方法如果需要改变结构体本身 使用的方法需要使用mutating进行修饰,如果说我们在上面的adjust中不对结构体做任何修改的话,比如说单纯的打印一段文字,不加mutating也是可以的。2.2 类class使用协议
//类使用协议class SimpleClass: ExampleProtocol { //如果在编译时不满足协议要求,Swift会报错 var simpleDescription: String = "A simple " var anotherProperty: Int = 69105 func adjust() { simpleDescription += "class." }}var a = SimpleClass()a.adjust()let aDescription = a.simpleDescriptionprint(aDescription) //"A simple class.\n"//类中的方法因为本身就可以改变类所以adjust方法不需要mutating关键字修饰2.3 枚举enum使用协议
//枚举使用协议enum SimpleEnum:ExampleProtocol { case out mutating func adjust() { print(self.simpleDescription + "enum.") } var simpleDescription: String{ get { switch self { case .out: return "A simple " } } }}var c = SimpleEnum.outc.adjust()//输出:A simple enum.3. 方法要求
协议可以要求指定实例方法和类型方法被一致的类型实现。这些方法被写为协议定义的一部分,跟普通实例和类型方法完全一样,但是没有大括号或方法体。可变参数是允许的,普通方法也遵循同样的规则。
3.1 方法协议注意:协议为普通方法使用相同的语法,但不允许给方法参数指定默认值。
方法协议: 定义时没有花括号执行体. 实现仅要求名称相同.
//协议内定义方法使用static进行定义,但是在实现时还是按照上面的规则:在struct或enum中仍然使用static。在class里使用class关键字时表示可overrIDe的类型方法实现,而在class里使用static关键字时表示不可overrIDe的类型方法实现protocol MyProtocol { static func foo() -> String}struct MyStruct: MyProtocol { static func foo() -> String { return "MyStruct" }}enum MyEnum: MyProtocol { static func foo() -> String { return "MyEnum" }}class MyClass: MyProtocol { class func foo() -> String { return "MyClass,可overrIDe的类型方法实现" }}class MyClass1: MyProtocol { static func foo() -> String { return "MyClass,不可overrIDe的类型方法实现" }}3.2 构造方法协议
构造方法协议: 可以要求遵从者实现指定的构造方法.
实现时用 required init(编译器会自动提示添加)
//必须实现,实现时用 required init(编译器会自动提示添加)protocol 带参数的构造方法协议 { init(某参数: Int)} class 某类: 带参数的构造方法协议 { required init(某参数: Int) { } } protocol 构造方法协议 { init() } class 某类1: 构造方法协议 { required init() { } }
如果子类与父类同时遵从某构造方法协议,则子类构造方法须加overrIDe required
protocol 构造方法协议 { init()}class 父类 { init() { }}class 子类: 父类,构造方法协议 { overrIDe required init() { }} 4. 协议扩展 协议扩展: 即使无源码权限下,给已有的类添加协议.
//1.既存实例会自动遵从添加了的协议.protocol ProtocolForInt { var description:String {get} mutating func addOne()}extension Int:ProtocolForInt { mutating func addOne() { self += 1 } var description: String { return "This number is \(self)" }}var abc:Int = 4abc.addOne() //5print(abc.description) //"This number is 5\n"//2.如果一个类型预遵从了协议,可以直接扩展协议struct MyText { var text: String //注意:即使满足了协议要求,类型也不会自动转变,必须为它做出明显的协议声明。 var description: String { return "我的自定义显示:" + text }}//customstringconvertible协议内含有必须实现的var description: String参数的可获取方法extension MyText: customstringconvertible {}//协议扩展let text1 = MyText(text: "3天学会Swift 3")print(text1)/* 协议扩展时text1输出为"我的自定义显示:3天学会Swift 3\n" 屏蔽上面的协议扩展则text1输出为"MyText(text: "3天学会Swift 3")\n" */5. 协议的继承
协议能够继承一到多个协议。语法与类继承基本相同。
protocol inheritingProtocol: SomeProtocol,AnotherProtocol { }6. 协议实现 6.1 协议的默认实现
//自定义一个可打印和可预览协议//customstringconvertible协议需满足var description: String要求//CustomPlaygroundQuickLookable协议需满足var customPlaygroundQuickLook: PlaygroundQuickLook要求protocol MyPrintable: customstringconvertible,CustomPlaygroundQuickLookable {}//提供默认实现: 可以给协议扩展提供一个默认的实现,任何遵从此协议的类型都会获得.extension MyPrintable { var description: String { return "控制台: 默认描述" } var customPlaygroundQuickLook: PlaygroundQuickLook { return PlaygroundQuickLook.text("playgroud预览: 默认值")// return PlaygroundQuickLook.color(UIcolor.blue) }}//1.采用默认实现struct MyText { var text: String}//MyText采用默认实现extension MyText: MyPrintable {}let text1 = MyText(text: "abcd") //"控制台: 默认描述\n"print(text1) //"控制台: 默认描述\n"//2.不采用默认实现struct MyText1 { var text: String}//MyText1不采用默认实现extension MyText1: MyPrintable { var description: String { return "print时的预览:" + self.text } var customPlaygroundQuickLook: PlaygroundQuickLook { return PlaygroundQuickLook.text("我的Text快速预览:" + self.text) }}let text2 = MyText1(text: "efg") //"我的Text快速预览:efg"print(text2) //"print时的预览:efg\n"6.2 协议中的必需实现和可选实现方法
//协议扩展//swift 中可选协议方法的实现protocol SwiftDiagonProtocol{ //必须 func requiredMethod() //可选 func optionalMethod()}//方法1:空实现(方法2:将可选实现和必需实现分为2个协议)extension SwiftDiagonProtocol{ func optionalMethod(){ //空实现也可以 }}class SwiftClass: SwiftDiagonProtocol{ func requiredMethod() { //Someting } //如果需要实现可选方法则实现,这里的实现会覆盖extension中的默认实现 func optionalMethod(){ //Something }}7. 类专用协议
可以在协议的继承列表中,通过添加关键字『class』,限制协议只能适配到类(class)型,结构和枚举不能遵循该协议。
protocol 一个协议: class,CustomPlaygroundQuickLookable {}class myText { var text = "22"}extension myText: 一个协议{ var customPlaygroundQuickLook: PlaygroundQuickLook { return PlaygroundQuickLook.text(self.text) }}let text = myText() //22text.text //22text.customPlaygroundQuickLook //text("22")print(text) //输出"myText\n",text本身仍然是myText类 8. 协议组合 协议组合: 多个协议临时组合在一起的类型. 形式: 协议1 & 协议2 & …>
protocol 年龄协议 { var 年龄 : Int { get }}protocol 姓名协议 { var 姓名: String { get }}struct 学生: 年龄协议,姓名协议,CustomPlaygroundQuickLookable { var 年龄: Int var 姓名: String var customPlaygroundQuickLook: PlaygroundQuickLook { return PlaygroundQuickLook.text(self.姓名 + ":\(self.年龄)岁") }}//无论传递的寿星是何类型,只要遵从年龄和姓名协议即可,参数大大自由化.func 生日祝愿(寿星: 年龄协议 & 姓名协议) { print("祝",寿星.姓名,寿星.年龄,"岁生日快乐!")}let 学生1 = 学生(年龄: 20,姓名: "洪荒少女") //"洪荒少女:20岁"生日祝愿(寿星: 学生1) //输出:祝 洪荒少女 20 岁生日快乐! 9. 协议的检查和转换 9.1 协议的检查 is struct Person: OneProtocol {}let p1 = Person()if (p1 is OneProtocol){ //可以理解为:p1 是一个遵守了OneProtocol协议类型的实例 print("yes")}//输出:yes9.2 协议的转换 as
protocol Coder { var name :String {get set} var updating: String { get }}struct AndroIDCoder: Coder { var name: String var updating: String { return "安卓程序员学iOS开发" }}struct DotNotCoder: Coder { var name: String var updating: String { return ".NET程序员学Swift 3" }}struct NewBIE { var name: String}let a = AndroIDCoder(name: "小米")let d = DotNotCoder(name: "小猫")let x = NewBIE(name: "小狗")let coders:[Any] = [a,d,x]for coder in coders { //as *** 作符用来把某个实例转型为另外的类型,由于实例转型可能失败,因此Swift为as *** 作符提供了两种形式:选项形式as?和强制形式as! //as? 如果转换不成功的时候便会返回一个 nil 对象,如果能确保100%会成功的转换则可使用 as!,否则使用 as? //as!由于是强制类型转换,如果转换失败会报 runtime 运行错误。 if let coder1 = coder as? Coder { print(coder1.updating) } else { print("你不是程序员!你会很辛苦的!") } if let xiaobo = coder as? NewBIE { print("你是"+xiaobo.name) }}/*输出: 安卓程序员学iOS开发 .NET程序员学Swift 3 你不是程序员!你会很辛苦的! 你是小狗 */ 10. 类型约束 func findindex<T: Equatable>(array: [T],valuetoFind: T) -> Int? { var index: Int? for (i,value) in array.enumerated() { if (value == valuetoFind) { index = i } } return index}var testArray = [1,2,3,4]findindex(array: testArray,valuetoFind: 3) //2//swift标准库定义了一个Equatable协议,该协议要求任何遵循该协议的类型实现(==)和(!=)对任何两个该类型进行比较。所有的swift标准类型自动支持Equatable协议。 11. 其他 类中在协议中没有定义的属性,我们是无法访问的
protocol ProtocolForInt { var description:String {get} mutating func addOne()}class SimpleClassForInt:ProtocolForInt { var number = 0 var description: String = "这是一个描述" func addOne() { number += 1 }}var simpleClassForInt:ProtocolForInt = SimpleClassForInt()print(simpleClassForInt.description) //"这是一个描述\n"simpleClassForInt.addOne()simpleClassForInt //number:1,description:"这是一个描述"//print(simpleClassForInt.number) //错误,类中在协议中没有定义的属性,无法访问 我们可以看到只有协议中定义的属性和方法是我们可以访问的,类中在协议中没有定义的属性,我们是无法访问的。
尽管simpleClassForInt的运行时(Runtime)类型是SimpleClassForInt,但是编译器还是会把它视为ProtocolForInt类型,所以在协议之外的属性和方法在simpleClassForInt中是无法访问的。
参考自
SwiftV课堂视频源码
http://c.biancheng.net/cpp/html/2433.html
http://www.wendq.com/wd/201702/14136.html
http://www.jianshu.com/p/09d312dac288
http://www.jb51.cc/article/p-azvphnod-qq.html
以上是内存溢出为你收集整理的swift3 协议全部内容,希望文章能够帮你解决swift3 协议所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)