Swift:协议专题

本文详细探讨了Swift中的协议,包括协议的使用规范、构造函数、关联值、标准库中的常见协议、协议扩展和默认实现、泛型约束以及可选协议方法。重点讲解了协议在继承、扩展和类型约束中的应用,旨在帮助开发者更好地理解和运用Swift协议。
摘要由CSDN通过智能技术生成

1. 协议初体验

强调的几点:

(1)协议里只能用var并且一定要注明是只读还是可读可写

(2)协议可以规定只被类继承,不能规定只被结构体继承

(3)即使协议中是只读的,但是我继承的类或者结构体仍然可以用var来实现,相当于在只读的基础上,多加了一个可写功能,但是并不破坏原有可读的属性,所以是允许的。反之不行,如果原来在协议里就是定义可读可写,则在继承的类或者结构体中不能用let去定义,只能用var

(4)属性可以是协议类型的,并且可以将一个实现过该协议的结构体或者类类型的实例赋值给这个属性,但是这个属性仍要优先遵循协议里面的相关约束

(5)协议也可以有构造函数,继承协议的类的构造函数一定要用required,当然特例是类前面有final

   (6) 协议的属性,继承之后必须赋初值,不管是直接赋初值也好还是以构造函数的方式也好,还是以计算型属性的方式也好。注意,如果要以计算型属性的方式来实现协议中的属性,就要看协议中是只读还是可读可写,对应设置计算型属性的getter和setter方法

具体代码如下

import Foundation

protocol Pet {
    
    var name: String {get set} // 继承他的时候不一定非要是计算型属性
    let birthPlace: String {get} // 只读
    
    func playWith()
    func fed(food: String)
}

struct Dog: Pet {
    var name: String = "Puppy" // 这里不能写let,因为协议中规定是可读可写,你这里相当于不遵守协议了
    var birthPlace = "Wuhan" // 协议里面是let,这里是var,相当于是在可读的基础上我加了一个可写
    
    func playWith() {
        print("Happy!")
    }
    
    func fed(food: String = "bone") {
        print("I love eating \(food)!")
    }
    
    mutating func changeName(newName: String) {
        name = newName
    }
}

var myDog: Dog = Dog()
var aPet: Pet = myDog // 这里和继承那一章很像,Pet类型的aPet可以存放其子类的对象

myDog.birthPlace = "Hankou" // 不报错,因为Dog结构体中是可读可写的
aPet.birthPlace = "Wuchang" // 报错,因为Pet协议中是只读的

2. 协议和构造函数

import Foundation

protocol Pet {
    
    var name: String {get set} // 继承他的时候不一定非要是计算型属性
    var birthPlace: String {get} // 只读
    
    func playWith()
    func fed(food: String)
    
    init(name: String) // 协议也可以有构造函数
}

class Animal {
    var type: String = "mammal"
}

class Dog: Animal, Pet {
    var name: String = "Puppy" // 这里不能写let,因为协议中规定是可读可写,你这里相当于不遵守协议了
    var birthPlace = "Wuhan" // 协议里面是let,这里是var,相当于是在可读的基础上我加了一个可写
    
    required init(name: String) { // 子类也必须继承
        self.name = name
    }
    
    func playWith() {
        print("Happy!")
    }
    
    func fed(food: String = "bone") {
        print("I love eating \(food)!")
    }
    
    func changeName(newName: String) {
        name = newName
    }
}

class Bird: Animal {
    var name: String = "Little bird"
    init(name: String) {
        self.name = name
    }
}

class Parrot: Bird, Pet {
    required override init(name: String) { // 这里的required是协议必须遵守的,要加required,要加override是因为构造函数和父类一样,所以要加override关键字
        super.init(name: name + " " + name)
    }
    
    func playWith() {
        print("gugugu")
    }
    
    func fed(food: String) {
        print("Thanks~")
    }
    
    let birthPlace: String = "Wuhan" // 这里没有name,是因为虽然Pet中规定了必须要有name,但是Parrot的父类已经有name了所以不需要
}

3. 举个?

import UIKit
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) // 子类指定的构造函数一定要用init
    }
}

class Sparrow: Bird {
    var color = UIColor.gray
}

class Vehicle {
    
}

class Plane: Vehicle, Flyable {
    var flySpeed: Double
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值