iOS --- 协议部分(swift2.3)

iOS — 协议部分(swift)

下面简单的介绍协议部分的应用

  1. 协议基础

  2. 协议和构造函数

  3. 为什么使用协议

  4. 类型别名(typealias)和光联类型(associated type)

  5. 标准库中常用的协议


一:协议基础
protocol Pet{
    //: 协议里面的属性,只能说明是可读还是可写
    // 对于属性,不能有初始值
    var name: String{ get set }// = "My Pet"
    // 统一使用var关键字
    var birthPlace: String{ get }
    // 对于属性,get,set隐藏了实现细节,可以使用let实现只读,也可以使用只有get的计算型属性


    //注意:协议里面的方法只写协议的申明,不写协议的实现方法,这是协议里面方法的特殊地方,而这个方法是怎么实现的,有遵守这个协议的类和机构来管理的
    // 对于方法,不能有实现
    func playWith()

    // 对于方法,不能有默认参数(默认参数就是一种实现)
    //func fed(food: String = "leftover")
    func fed()
    func fed(food: String)

    // 可以使用mutating关键字,强调这个方法应该修改其内容
    mutating func changeName(newName:String)

    // 不可以设置访问控制
    // 协议就是协议,如果开发者可以看见协议,就可以看见协议里的任何内容
}

// 不能实例化Pet
//var pet = Pet()


// 协议的继承
protocol PetBird: Pet{

    var flySpeed: Double{ get }
    var flyHeight: Double{ get }
}


// 协议的实现,实现协议规定的所有属性和方法即可
struct Dog: Pet{

    // 可以使用计算型属性
//    private var myDoggyName = "Puppy"
//    var name: String{
//        get{
//            return myDoggyName
//        }
//        set{
//            myDoggyName = newValue
//        }
//    }
    var name: String

    // protocol的read-only,对一个具体类的实现,不一定只读,但是作为Pet是只读的!
    //let birthPlace: String
    var birthPlace: String


    func playWith() {
        print("Wong!")
    }

    func fed(){
        print("I want a bone.")
    }

    // 在具体实现上可以加默认参数
    func fed(food: String = "Bone"){

        if food == "Bone"{
            print("Happy")
        }
        else{
            print("I want a bone")
        }
    }

    // 对于class,不需要mutating关键字
    mutating func changeName(newName: String) {
        name = newName
    }
}


let myDog:Dog = Dog(name: "summer", birthPlace: "beijing")

// 从Pet的角度看,myDog的birthPlace是只读的!
let aPet: Pet = myDog
//aPet.birthPlace = "shanghai"
二:协议和构造函数
protocol Pet{

    var name: String{ get set }

    init(name: String)

    func playWith()
    func fed()
}

class Animal{

    var type: String = "mammal"
}


// 如果一个类有继承的类,则父类必须放在前面
class Dog: Animal, Pet{

    // 如果protocol没有init(name)的要求,name有默认名字就够了
    var name: String = "Puppy"

    // 如果protocol有init,则在class中必须注明required
    required init(name: String){
        self.name = name
    }

    func playWith() {
        print("Wong")
    }

    func fed(){
        print("I love bones")
    }
}


final class Cat: Animal, Pet{

    var name: String = "Kitten"

    // 如果是final class, init可以没有required, 因为也不会再被继承了
    init(name: String){
        self.name = name
    }

    func playWith() {
        print("Meow")
    }

    func fed(){
        print("I love fish")
    }
}


class Bird: Animal{

    var name: String = "Little Little Bird"

    init(name: String){
        self.name = name
    }
}


// 如果只是继承Bird,Bird的init为required,则override可以省略
// 否则,必须有override, 可以没有required
// 因为有Pet,则required也不能省
class Parrot: Bird, Pet{

    required override init(name: String){
        super.init( name: name + " " + name )
    }

    func playWith() {
        print("Hello")
    }

    func fed(){
        print("Thank you!")
    }
}
三:为什么使用协议
protocol Pet{
    var name: String {get set}
}

protocol Flyable{
    var flySpeed: Double {get}
    var flyHeight: Double {get}
}


class Animal{
}

class Dog: Animal, Pet{
    var name = "Puppy"
}

class Cat: Animal, Pet{
    var name = "Kitten"
}

class Bird: Animal, Flyable{

    var flySpeed: Double
    var flyHeight: Double

    init(flySpeed: Double, flyHeight: Double){
        self.flySpeed = flySpeed
        self.flyHeight = flyHeight
    }
}

class Parrot: Bird, Pet{

    var name: String

    init(name: String, flySpeed: Double, flyHeight: Double){
        self.name = name + " " + name
        super.init(flySpeed: flySpeed, flyHeight: flyHeight)
    }
}

class Sparrow: Bird{

    var color = UIColor.grayColor()
}


class Vehicle{

}

class Plane: Vehicle, Flyable{

    var model: String
    var flySpeed: Double
    var flyHeight: Double

    init(model: String, flySpeed: Double, flyHeight: Double){
        self.model = model
        self.flySpeed = flySpeed
        self.flyHeight = flyHeight
    }
}


var dog = Dog()
var cat = Cat()
var parrot = Parrot(name: "hi", flySpeed: 10.0, flyHeight: 100.0)

let pets: [Pet] = [dog, cat, parrot]
for pet in pets{
    print(pet.name)
}


var sparrow = Sparrow(flySpeed: 15.0, flyHeight: 80.0)
var plane = Plane(model: "Boeing 747", flySpeed: 200.0, flyHeight: 10_000.0)

let flyers: [Flyable] = [parrot, sparrow, plane]
for flyer in flyers{
    print("Fly speed: " , flyer.flySpeed , "Fly Height: " , flyer.flyHeight)
}
四:类型别名(typealias)和光联类型(associated type)

1.给一般类型起别名(typealias)

//这里就是给double起了一个别名
typealias Length = Double

extension Double{
    //计算型属性可以直接用return返回就是
    var km: Length{ return self * 1000.0 }
    var m: Length{ return self }
    var cm: Length{ return self / 100 }
    var ft: Length{ return self / 3.28084 }
}

let runningDistance: Length = 3.54.km//标准库的扩展直接这样写就是,调用方法也一样
runningDistance


typealias AudioSample = UInt64

2.在协议里面给一个类型其别名()(associated type)

// 新版本中,在Protocol中声明,用associatedtype
protocol WeightCalculable {

    associatedtype WeightType//首先在协议里面给WeightType起一个别名,但是不给别名赋值,直到真正用到的时候,再给别名赋值

    var weight: WeightType { get }
}


// 在具体实现中,用typealias
class iPhone7: WeightCalculable{//遵守了协议就要实现协议里面的方法和属性

    typealias WeightType = Double//在用到别名的时候再给别名赋值,但是注意协议里的别名关键字是associatedtype,而结构和类中关键字为typealias

    var weight: WeightType{
        return 0.114
    }
}

class Ship: WeightCalculable{

    typealias WeightType = Int

    var weight: WeightType

    init(weight: Int){
        self.weight = weight
    }
}

extension Int{//这里其实就是int增添一个计算型属性,如果一个数.t,那么就是返回一千倍
    typealias Weight = Int
    var t: Weight{return 1_000*self}
}

let titanic = Ship(weight: 46_328_000)

let good = Ship(weight: 46_328.t)
五:标准库中常用的协议

// Equatable, Comparable,协议


// Equatable and comparable
struct Record: Equatable, Comparable{
//Equatable协议是对“==”运算符进行重载,Comparable协议是对所有比较运算符重载,这里只需要最“<”运算符进行重载就是

    var wins: Int
    var losses: Int
}
// 必须紧跟着写,不能在中间插入任何语句
func ==(left: Record, right: Record) -> Bool{
    return left.wins == right.wins && left.losses == right.losses
}
func <(left: Record, right: Record) -> Bool{
    if left.wins != right.wins{
        return left.wins < right.wins
    }
    return left.losses > right.losses
}

let recordA = Record(wins: 10, losses: 5)
let recordB = Record(wins: 10, losses: 5)

recordA == recordB

// 不仅仅是重载 == 的意义在于,告诉别人,我是Equatable的!
var team1Record = Record(wins: 10, losses: 3)
var team2Record = Record(wins: 8, losses: 5)
var team3Record = Record(wins: 8, losses: 8)
var records = [team1Record,team2Record,team3Record]

records.sort()

//CustomStringConvertible, BooleanType协议

// CustomStringConvertible:可以有自定义打印格式。 and BooleanType
struct Record: Equatable, Comparable, CustomStringConvertible, BooleanType{

    var wins: Int
    var losses: Int

    var description: String{
        return "WINS: " + String(wins) + " , LOSSES: " + String(losses)
    }

    var boolValue: Bool{
        return wins > losses
    }
}
func ==(left: Record, right: Record) -> Bool{
    return left.wins == right.wins && left.losses == right.losses
}
func <(left: Record, right: Record) -> Bool{
    if left.wins != right.wins{
        return left.wins < right.wins
    }
    return left.losses > right.losses
}


let record = Record(wins: 10, losses: 5)

print( record )

if record{
    print("Great!")
}


// 可以在extension中实现协议!
// 局限:不能使用存储型变量
extension Int: BooleanType{
    public var boolValue: Bool{
        return self != 0
    }
}

var wins = 0
if !wins{
    print("You never win!")
}
//以后出现ble后缀的协议,意思就是这个协议描述的是什么特性,type结尾的协议描述的是可以成为什么类型
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值