(实验)Swift 面向协议

协议

swift中协议中可以声明属性,静态属性,方法,静态方案

protocol IPerson {
    //属性 协议总是用 var 关键字来声明变量属性,
    //在类型声明后加上 { set get } 来表示属性是可读可写的,可读属性则用 { get } 来表示:
    var name:String{get set}
    //static属性
    static var address:String{get set}
    //方法
    func eat()
    //static方法
    static func helloWord()
}

class Chinese: IPerson {
    var name: String = ""
    static var address: String = "china"
    func eat() {
        print("Chinese eating now......")
    }
    static func helloWord() {
        print("helloWord......")
    }
}

子类如果继承了协议而不去实现其中的内容,编译就会通不过

协议的extension实现

在Swift中 协议可以直接由协议的extension实现,继承协议的子类可以直接调用,看Demo

protocol IPerson {

}

extension IPerson
{
    func speak()
    {
        print("speaking now......")
    }
}

class Chinese: IPerson {

}

let anson = Chinese()
anson.speak()

如代码所示,我们甚至在IPerson不声明speak函数,子类就能调用

可选的协议

协议可以定义可选要求,遵循协议的类型可以选择是否实现这些要求。在协议中使用 optional 关键字作为前缀来定义可选要求。可选要求用在你需要和 Objective-C 打交道的代码中。协议和可选要求都必须带上@objc属性。标记 @objc 特性的协议只能被继承自 Objective-C 类的类或者 @objc 类遵循,其他类以及结构体和枚举均不能遵循这种协议。

@objc protocol IAnimal {
    @objc optional func sprak()
    @objc optional var name:String{get}
    @objc optional func variety() -> String
}

class Dog: IAnimal
{
    func jump() {
        print("Dog jump....")
    }
    
    var name: String{
        return "dog"
    }
    
    func variety() -> String {
        return "black"
    }
}

let dog:IAnimal = Dog()
print(dog.name ?? "")
print(dog.variety!())

协议中的可选要求可通过可选链式调用来使用,因为遵循协议的类型可能没有实现这些可选要求。
需要注意的是整个函数类型是可选的,而不是函数的返回值。

associatedtype

在Swift中,class、struct、enums都可以是用参数化类型来表达泛型的,只有在协议中需要使用associatedtype关键字来表达参数化类型

协议在Swift中有两个目的,第一个目的是用来实现多继承(swift语言被设计为单继承的),第二个目的是强制实现者必须准守自己所指定的泛型约束。关键字associatedtype是用来实现第二个目的的

泛型的实现方式

下面例子中的associatedtype实现了类似泛型的作用

protocol ICooker {
    associatedtype foodType
    func barbecue(food:foodType)    //烤*
    func saute(food:foodType)    //炒*
    
}

class Chicken {}
class Corn {}

//高级厨师可以烤肉或者炒肉
class SuperCooker: ICooker {
    typealias FoodType = Chicken
    func barbecue(food:FoodType)    //烤肉
    {
    }
    func saute(food:FoodType)       //炒肉
    {
    }
}
//一般厨师只会烤玉米或者炒玉米
class GeneralCooker: ICooker {
    typealias FoodType = Corn
    func barbecue(food:FoodType)    //烤玉米
    {
    }
    func saute(food:FoodType)       //炒玉米
    {
    }
}

判断是否符合协议

这个直接看代码

protocol ITest {
    var name:String {get set}
}

class Test: ITest {
    var name = "I am Test"
}

class Dog {
    var name = "I am dog"
}

let arr:[AnyObject] = [Dog(),Test()]

arr.forEach { (item) in
    if let item = item as? ITest {  //用强转来判断
        print("find ITest: " + item.name)
    } else {
        print("not find")
    }
}

输出

not find
find ITest: I am Test

协议的约束

限定允许集成协议的类型

protocol 后面加上约束关键字【where】,并注明该协议只能被某个类(包括子类)所遵守

比如

class Person {}

protocol IPerson where Self : Person {}

extension IPerson
{
}

class Chinese: Person,IPerson {}

//class Dog:IPerson{} 编译不通过

上面的Dog继承IPerson 编译器报错'IPerson' requires that 'Dog' inherit from 'Person'
这个限定对于协议也可以

protocol ISpeak {}
protocol IPerson where Self : ISpeak {}

extension IPerson
{
}

class Chinese: ISpeak,IPerson {}

//class Dog:IPerson{} //编译不通过

上面的 Chinese继承了ISpeak协议,符合IPerson协议的条件,所以能编译通过 Dog未继承ISpeak协议,编译失败

对具体类型的扩展

上面的例子约束了子类的类型,编译器会帮我们去判断这个约束,但是有的时候我们需要对不同的类进行不同的扩展方法
比如下面

protocol ISpeak {}

class Chinese: ISpeak {}
class Dog:ISpeak{} 

我想给Chiese和Dog不同的speak方法实现,那么可以这样

protocol ISpeak {}

class Chinese: ISpeak {}
class Dog:ISpeak{}

extension ISpeak where Self : Chinese
{
   func speak()
   {
        print("Hollo word!")
    }
}

extension ISpeak where Self : Dog
{
    func speak()
    {
        print("wang wang  wang~~~")
    }
}
Chinese().speak()
Dog().speak()

输出

Hollo word!
wang wang  wang~~~

这里利用了协议的extension的约束对不同的子类进行了扩展

你可能感兴趣的:((实验)Swift 面向协议)