每天学一点Swift----面向对象下(七)

43 篇文章 0 订阅
42 篇文章 0 订阅
本文介绍了Swift中的协议使用,包括协议作为类型声明变量、作为函数参数及返回值类型,以及如何实现协议。同时讲解了合成协议的概念,通过扩展为已有类型添加协议的实践,并提到了唯类协议的定义及其优势。通过具体示例展示了面向协议编程的灵活性和多态价值。
摘要由CSDN通过智能技术生成

十一.使用协议作为类型

1. 协议也相当于一种类型,与枚举、结构体、类相比,协议相当于一种抽象的类型,它被彻底抽象成只定义规范,不负责实现。因此定义协议之后,就可以像枚举、结构体、类那样当作类型来使用,只是协议不能直接用于创建实例,协议可以做如下方面的用途

1)可使用协议声明变量

2)可使用协议作为函数、方法、构造器的形参类型、返回值类型

3)可使用协议作为isas等运算符的  *** *** 一个操作数


2. 举个栗子:

protocol Eatable

{

   //定义实例方法

   Func taste()

   //协议使用class修饰类型方法

   class func test(msgs : String…)


//实现Eatable协议

struct Pie : Eatable

{

   var weight : Double

   //定义实例方法

   func taste()

   {

print(“饼干很好吃。。。”)

   }

   //结构体使用static修饰类型方法

   static func test (msgs : String…)

   {

print(“test method”)

for msg in msgs

{

    print(“msg is: ”\(msg))

}

   }

}


class Apple : Eatable

{

   var name : String

   init(name : String)

   {

self.name = name

   }

   //定义实例方法

   func taste()

   {

print("苹果很好吃")

   }

   //类使用class修饰类型方法

   class func test (msgs : String...)

   {

print("apple test")

   }

}


//使用Eatable声明变量,将Apple实例赋值给food,这是向上转型

var food1 : Eatable = Apple(name : "红富士")

//使用Eatable声明变量,将Pie实例赋值给food,这是向上转型

var food2 : Eatable = Pie(weight : 1.2)

//分别调用food1food2里面的方法,这是多态

food1.taste()

food2.taste()

//定义一个函数,该函数的形参是个数可变的Eatable类型的形参

func eat(foods : Eatable...)

{

   for food in foods

   {

food.taste()

   }

}

//由于该函数的参数要求是Eatable类型,所以既可以传入Apple,也可以传入Pie

eat(Apple(name : "apple"), Pie(weight : 2.2))


//声明并反问Eatable类型的数组

var foodArray : [Eatable] = [Apple(name : "apple1"), Pie(weight : 1.2),Apple(name : "apple2"), Pie(weight : 2.2),Apple(name : "apple3"), Pie(weight : 3.2),Apple(name : "apple4"), Pie(weight : 4.2)]


for food in foodArray

{

   if let ap = food as? Apple

   {

print("这个Eatable是苹果,名字为:\(ap.name)")

   }

   else let pie = food as? Pie

   {

print("这个Eatable是饼干,重量为: \(pie.weight)")

   }

}


3. 通过上面可以看出,实现某个协议时,也集成某个类的本质是一样的,协议的实现类型,也相当于协议的特殊子类,因此协议实现类型的实例,完全可以当成协议实例使用。


4. 一般来说,程序通常应该面向协议编程,就像其他语言倡导的面向接口编程一样,面向协议编程能提供更好的灵活性,这也是多态的价值所在。


十二.合成协议

1. Swift还允许将多个协议合成一个临时的类型,这种用法被为合成协议。合成协议的语法格式为:

   protocol<协议1协议2协议3 ....>

2. 对于采用这种合成协议声明的变量、定义的参数、声明的返回值,必须同时实现合成协议里面的所有协议。



十三.通过扩展为已有的类型添加协议

1. 前面已经知道通过扩展可以为已有的类型添加计算属性、方法、下标、构造器等。不仅如此,使用扩展还可以为已有的类型添加协议。


2. 举个栗子:下面的代码通过扩展让String实现Eatable协议。

extension String : Eatable

{

   //实现Eatable协议中的方法

   func taste()

   {

   print("\(self) taste")

   }

   class func test()

   {  // ....  }

   

}


3. 在某些极端情况下,如果已有类型已经实现了协议中的要求,则可以更简单地通过扩展让该类型实现这个协议————此时扩展的花括号内不需要任何代码


4. 举个栗子:

protocol Emptyable

{

   var isEmpty : Bool {get}

}


extension String : Emptyable{}


//定义一个方法,该方法需要Emptyable参数

func foo(arg: Empayable)

{

   print("arg is empty or not : (\arg.isEmpty)")

}

//调用foo方法,传入String即可,(因为String实现了Emptyable协议)

foo("abc")

foo("")



十四.唯类协议

1. Swift还支持定义一种唯类协议,这种协议  **只能被类实现,不能被枚举、结构体实现,如果程序中使用枚举、结构体实现唯类协议,编译器会报错。


2. 定义唯类协议非常简单,只要在定义协议的协议名后面的冒号后面紧跟class关键字即可(class放在所有父协议的第一位):

protocol 协议名 class父协议1父协议2,...

{

   //唯类协议的定义。

}


3. 唯类协议中无须定义mutating方法(定义了也没用,因为只有类才能实现唯类协议,类的方法本身就可以修改实例属性),除此之外,唯类协议与普通协议基本相同。


4. 使用唯类协议的优势在于:Swift总是将唯类协议当成引用类型处理,而不会当成值类型处理。这是因为唯类协议的实现者只能是类,因此肯定是引用类型。


5. 举个栗子:

protocol Movable : class

{

  func move()

}


class Car : Movable

{

   func move()

   {

print("move in car")

   }

}


struct Bee : Movable  ----这里将会报错

{

   func move()

   {

print("move in bee")

   }

}

var move : Movable? = nil

上面的代码中,由于Movable是一个唯类协议,因此系统可以直接将move变量当成引用类型处理。


上一篇:每天学一点Swift----面向对象下(六)

下一篇:每天学一点Swift----面向对象下(八)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值