美文网首页Swift Advance
Swift面向协议编程(和面向对象的对比)-基础版

Swift面向协议编程(和面向对象的对比)-基础版

作者: Hellolad | 来源:发表于2018-03-26 00:02 被阅读50次

引言:最近研究了一下面向协议编程,来谈一下自己的理解和使用体会.

首先,2015年WWDC大会上,swift宣布swift2是一门支持面向协议编程的语言,当时完全不知道面向协议编程到底是什么东西,因为平时在开发项目的过程中一直都在使用面向对象的思想去编程和开发。

其实说白了面向协议编程就是一种编程思想,只要在开发的过程中多想,多思考,你也完全可以创造出来另一种编程思想。

在swift中,真的,协议真的是强大的不得了,他可以做的事情太多了,在我熟知的集中编程语言中,基本上除了class能遵守协议之外,其他的类型都没有遵守协议这种方式,而在swift中,class, struct, enum, protocol 都可以遵守协议,并且跟他很好的进行配合使用。

首先我们来看一下这四种类型遵守协议的代码:

protocol MyProtocol {}

class Person: MyProtocol {}
struct Car: MyProtocol {}
enum NotificationType: MyProtocol {}
protocol Equatable: MyProtocol {}

这种基础的相信大家都已经非常熟悉了,下面我们来说一下协议的扩展,这个,我觉得大家都也很熟悉,但是这个确实很有用处。

和其他类型一样,协议也可以进行扩展,可以为所有符合该协议的的类型提供公共方法

protocol MyProtocol {}
extension MyProtocol {
    func add_ABC(_ str: String) -> String {
        return str + "ABC"
    }
}

好处可想而知,全项目中唯独这一份代码,你不需要在你的类中去添加这些代码,只要你的类型遵守了这个协议,那么你自然就拥有了这个函数。

exp:

struct Person: MyProtocol {
    var name: String
}

let person = Person(name: "Henry")
let addABCName = person.add_ABC(person.name)
print(addABCName)
输出: HenryABC

<例子只是一个说明,无实际意义>

接下来我们来说下,swift中我们到底如何来使用面向协议的思想来编程。

最早以前我接触过C#, C#里面的这种东西叫委托,当时完全不知道这个东西是干什么使用的,只是老师告诉我们,这个委托,你就看做是老板,定义的函数就相当于是老板给你发的命令,他不管你会不会完成,他只是发命令的人,具体执行要你来完成。反正当时我是靠这个理解的委托的意义,不知道大家赞不赞同...

我们都知道,现在的项目中大多数用的思想还是面向对象,我们来举个实际的例子来说一下面向对象的思想:

首相我们来设计一个场景(请忽略我的设计·········实在不知道编什么)

动物:Animal
陆地动物:Dog     狗
两栖动物:Cabrite 蜥蜴
三栖动物:Duck 鸭子(瞎编一个)

狗只能在陆地上</br>
蜥蜴可以在陆地和水中

鸭子可以在空中陆地水中... 有点扯了

好了我们看代码

enum LifeStyle {
    case land
    case water
    case air
}

class Animal {
    var lifeStyles = [LifeStyle]()
    
    var landWalk: Bool = true
    var waterSwim: Bool = true
    var airFly: Bool = true
    
    func doLandWalk() {}
    func doWaterSwim() {}
    func doAirFly() {}
    
    func isLifeStyle(style: LifeStyle) -> Bool {
        return lifeStyles.contains(style)
    }
}

class Dog: Animal {
    override init() {
        super.init()
        
        lifeStyles = [.land]
        landWalk = true
        waterSwim = false
        airFly = false
    }
    
    override func doLandWalk() {
        print("Dog Land Walk")
    }
}

class Cabrite: Animal {
    override init() {
        super.init()
        
        lifeStyles = [.land, .water]
        landWalk = true
        waterSwim = true
        airFly = false
    }
    
    override func doLandWalk() {
        print("Cabrite Land Walk")
    }
    override func doWaterSwim() {
        print("Cabrite Water Swim")
    }
}

class Duck: Animal {
    override init() {
        super.init()
        
        lifeStyles = [.land, .water, .air]
        landWalk = true
        waterSwim = true
        airFly = true
    }
    
    override func doLandWalk() {
        print("Duck Land Walk")
    }
    override func doWaterSwim() {
        print("Duck Water Swim")
    }
    
    override func doAirFly() {
        print("Duck Air Fly")
    }
}

var animals = [Animal]()
var a1 = Dog()
var a2 = Cabrite()
var a3 = Duck()
animals.append(a1)
animals.append(a2)
animals.append(a3)

for (_, animal) in animals.enumerated() {
    if animal.isLifeStyle(style: .land) {
        print("animal Life Land")
        animal.doLandWalk()
    }
    if animal.isLifeStyle(style: .water) {
        print("animal Life Water")
        animal.doWaterSwim()
    }
    if animal.isLifeStyle(style: .air) {
        print("animal Life Air")
        animal.doAirFly()
    }
}
输出:
animal Life Land
Dog Land Walk
animal Life Land
Cabrite Land Walk
animal Life Water
Cabrite Water Swim
animal Life Land
Duck Land Walk
animal Life Water
Duck Water Swim
animal Life Air
Duck Air Fly

正确输出了我们所定义功能

狗仅仅在陆地生存

蜥蜴可以在陆地和水中

鸭子可以在水中陆地空中...(莫名的喜感)

OK,那么问题来了?

我觉得这样做已经很好了,面向协议的话题可以结束了,我用面向对象都能实现了为什么还要面向协议呢? 不急我们先看一下协议如何实现上面的这些东西

exp:

protocol Animal {
    
}

protocol LandAnimal: Animal {
    var landWalk: Bool {get}
    
    func doLandWalk()
}

protocol WaterAnimal: Animal {
    var waterSwim: Bool {get}
    
    func doWaterSwim()
}

protocol AirAnimal: Animal {
    var airFly: Bool {get}
    
    func doAirFly()
}


struct Dog: LandAnimal {
    let landWalk: Bool = true
    func doLandWalk() {
        print("Dog Land Walk")
    }
}

struct Cabrite: LandAnimal, WaterAnimal {
    let landWalk: Bool = true
    let waterSwim: Bool = true
    func doLandWalk() {
        print("Cabrite Land Walk")
    }
    func doWaterSwim() {
        print("Cabrite Water Swim")
    }
}

struct Duck:LandAnimal, WaterAnimal, AirAnimal {
    let landWalk: Bool = true
    let waterSwim: Bool = true
    let airFly: Bool = true
    func doLandWalk() {
        print("Duck Land Walk")
    }
    func doWaterSwim() {
        print("Duck Water Swim")
    }
    func doAirFly() {
        print("Duck Air Fly")
    }
}

var animals = [Animal]()
var a1 = Dog()
var a2 = Cabrite()
var a3 = Duck()
animals.append(a1)
animals.append(a2)
animals.append(a3)

for (_, animal) in animals.enumerated() {
    if let dog = animal as? Dog {
        dog.doLandWalk()
    }
    if let cabrite = animal as? Cabrite {
        cabrite.doLandWalk()
        cabrite.doWaterSwim()
    }
    if let duck = animal as? Duck {
        duck.doLandWalk()
        duck.doWaterSwim()
        duck.doAirFly()
    }
}
输出:
Dog Land Walk
Cabrite Land Walk
Cabrite Water Swim
Duck Land Walk
Duck Water Swim
Duck Air Fly

可以看出,首先协议的写法要比类的继承要简要很多,然后阅读起来也很方便,当然这不是一个主要的原因。

  1. 在面向对象中,我们的Dog类继承了Animal类,虽然我们知道Dog只有Lnad的属性,但是我们不可避免的一个问题就是我们的Dog是可以调用到doWaterSwimdoAirFly的,这是一个我觉得编程多年的开发也会遇到的错误,但是协议就不会,为什么,因为首先编译器就不会让你通过,因为Dog类在面向协议中并没有遵守WaterAnimal和AirAnimal
  1. 在面向对象中,我们的派生类只能把landwWalk的Book类型设置为变量,这样,我们就可以再类中做任何的更改,如果这样的话,那就会出现很多问题,但是在协议中就不会出现这种问题,首先你在定义的啥时候已经表明了 {get} 并且你可以在你的实现中用let来声明它是一个常量.

当然面向协议还有很多的好处,在编程中改变一下思想,其实就可以做到面向协议编程。

如果说面向协议和面向对象哪个好,我不敢说面向协议就一定比面向对象强,我只能说你的项目是否适用,当然swift的标准库中有太多的协议,可以说,swift是很推荐我们使用协议编程,所以,对于项目来说取优吧。一切以项目为主。

当然说道协议肯定离不开泛型,这篇我文章就不做介绍了,可以看我URLNavigator使用指南及扩展这篇文章,里面有用到协议和泛型的结合使用。

这也是我这两天理解和体会到的一些,也有很多不足的地方或者写的不好的地方,还请大家谅解,本文仅供参考,有好的意见大家尽管在下方留言。

相关文章

  • swift和OC的比较

    swift ----OC比较 编程范式 Swift 可以面向协议编程、函数式编程、面向对象编程。Objective...

  • swift注意事项

    一、编程范式 Swift 可以面向协议编程(POP)、函数式编程、面向对象编程。 Object-C 以面向对象编程...

  • Swift和OC的区别

    一、编程范式 Swift可以面向协议编程、面向函数编程、面向对象编程。 OC主要是面向对象编程。 二、类型安全 S...

  • Swift从入门到精通-1

    一、Swift和Objective-C比较 1、编程范式:Swift可以面向协议编程,函数式编程,面向对象编程;O...

  • Swift 中的面向协议编程

    Swift 中面向协议编程的应用,与面向对象不同的编程模式。在 Swift 这个现代化的编程语言中,感受面向协议带...

  • Swift和OC的主要区别

    编程范式 Swift 可以面向协议编程、函数式编程、面向对象编程。 Object-C 以面向对象编程为主,当然你可...

  • Swift面向协议编程(和面向对象的对比)-基础版

    引言:最近研究了一下面向协议编程,来谈一下自己的理解和使用体会. 首先,2015年WWDC大会上,swift宣布s...

  • Swift学习笔记1-oc与swift的区别

    编程范式Swift可以面向协议编程、函数式编程、面向对象编程OC以面向对象编程为主,当然你可以引入类似Reacti...

  • Swift和OC的区别

    一.编程范式 1.Swift可以面向协议编程,函数式编程,面向对象编程; 2.OC以面向对象编程为主,当然也可以引...

  • 17.Swift学习之类

    类介绍 Swift虽然推荐面向协议编程,但其也是一门面向对象开发的语言 面向对象的基础是类,类产生了对象(类的实例...

网友评论

    本文标题:Swift面向协议编程(和面向对象的对比)-基础版

    本文链接:https://www.haomeiwen.com/subject/zuclcftx.html