----协议的定义----
//协议:方法,属性或一段功能的蓝本
//协议可被类,结构体和枚举“领养”从而“长大成人”
//任何满足协议的“需求”的类型,被称为“遵从”该协议
protocol APro {
}
protocol BPro {
}
//领养/遵从若干个协议,用逗号分隔
struct AStruct : APro,BPro {
}
//超类在协议之前
class Name {
}
class GiveName:Name,APro,BPro {
}
----属性协议----
属性协议:顾名思义,要求遵从实现已制定的名称实现属性,但具体实现是实例属性或类型属性并不关心
//可以指定要求实现getter和setter+getter,属性必须定义为变量 var
protocol FileAccessPriority {
var readOnly : Bool { get }
var readWrite : Bool { get set}
}
protocol AccessUrl {
static var link:String {get}
}
//遵从实例属性协议 例子1
protocol FullName {
var fName : String {get}
var gNAme : String {get}
}
struct Student : FullName {
var gNAme: String
var fName: String
}
var stu1 = Student(gNAme: "老王", fName: "隔壁")
stu1.fName
stu1.gNAme
//遵从实例属性协议 例子2
class SomeBody : FullName {
var title: String?
var name: String
init(title:String? ,name:String) {
self.title = title
self.name = name
}
var gNAme: String {
return name
}
var fName: String {
return title ?? "无名小将"
}
var desc : String {
return self.fName + self.gNAme
}
}
var somebody1 = SomeBody(title: "大帝", name: "亚历山大")
somebody1.gNAme
somebody1.fName
somebody1.desc
var noBody = SomeBody(title: nil, name: "小波")
noBody.fName
noBody.gNAme
noBody.desc
----属性协议----
方法协议:定义使没有{}执行体,实现仅要求名称相同
作用:可以让一个类/结构体/枚举的方法,分解为更小的组合,从而更加灵活性
//类型方法协议:前缀总是static
protocol AMethod {
static func foo()
}
class A :AMethod {
class func foo() {
print("哈哈哈")
}
}
A.foo()
//实例方法协议
protocol RandomGeneratable {
func randomNumber() -> Int
}
struct RandomNumber :RandomGeneratable {
func randomNumber() -> Int {
return Int(arc4random())
}
}
struct RandomNumberInsix : RandomGeneratable {
func randomNumber() -> Int {
return Int(arc4random()) % 6
}
}
let random1 = RandomNumber()
random1.randomNumber()
let random2 = RandomNumberInsix()
random2.randomNumber()
//结构体,枚举的 “变异方法协议”
protocol Switchable {
mutating func onOff()
}
enum MySwitch : Switchable {
mutating func onOff() {
switch self {
case .off:
self = .on
default:
self = .off
}
}
case on,off
}
----构造方法协议----
构造方法协议:可以要求遵从者实现指定的构造方法
实现时用required init,编译器会提示添加,无需手动添加required
protocol AA {
init(a:Int)
}
struct B : AA {
init(a : Int) {
}
}
class C : AA {
required init(a: Int) {
}
}
//协议作为类型使用: 可用于参数类型/返回类型; 变量/常量/属性 ;集合类型中的元素类型
//实例方法协议
protocol RandomGeneratable {
func randomNumber() -> Int
}
struct RandomNumber :RandomGeneratable {
func randomNumber() -> Int {
return Int(arc4random())
}
}
class TenRandomNumber : RandomGeneratable{
func randomNumber() -> Int {
return Int(arc4random()) % 10 + 1
}
}
struct Dice {
var sides : Int
var randomNumber : RandomGeneratable
func play() -> Int {
return self.randomNumber.randomNumber() % sides + 1
}
}
let aDice = Dice(sides: 6, randomNumber: RandomNumber())
----协议作为代理----
协议作为代理:代理是一种常见的设计模式,可以让类或结构体把一部分职责,指派给非同类的实例去承担
/*
1.若要寻求代理,可以通过定义一个协议,打包要实现的职责于其中
2.该代理协议的遵从者就可以实现这些打包的职责
3.代理在IOS开发中,一般可以用于响应特定的操作,或从外部数据源取回数据但无需了解是何种数据源
*/
struct Role {
var name : String
}
protocol Player {
var role : Role {get}
mutating func play()
}
protocol GameDelegate {
func start(with player: Player) -> Int
func rolePK(with player: Player,armed:Bool) -> Int
func end(with player: Player) -> Int
}
struct GameAgent : GameDelegate {
func start(with player: Player) -> Int {
print(player.role.name,"开启游戏,获得经验,2000")
return 2000
}
func rolePK(with player: Player, armed: Bool) -> Int {
if armed {
print(player.role.name, "PK 开始,有武器,获得5000经验")
return 5000
} else {
print(player.role.name, "PK 开始,没有武器,获得2500经验")
return 2500
}
}
func end(with player: Player) -> Int {
print(player.role.name, "正常退出,获得1000经验")
return 1000
}
}
struct MirPlayer : Player {
var exp : Int
var gameAgent : GameAgent?
var role: Role
mutating func play() {
if let gameAgent = gameAgent {
print("您使用了代练")
exp += gameAgent.start(with: self)
exp += gameAgent.rolePK(with: self, armed: true)
exp += gameAgent.end(with: self)
} else {
print("您还没有开始代练,不能自动升级")
}
}
}
let role = Role(name: "小波")
var play1 = MirPlayer(exp: 0, gameAgent: nil, role: role)
play1.play()
let role2 = Role(name: "土豪玩家")
let agent = GameAgent()
var play2 = MirPlayer(exp: 0, gameAgent: agent, role: role2)
play2.play()
----协议扩展和约束-----
//协议扩展:即使无源码权限下,给已有的类添加协议
//即存实例会自动遵从添加了的协议
let a = 1
protocol ShowHint {
func hint() -> String
}
extension Int : ShowHint {
func hint() -> String {
return "整数:\(self)"
}
}
a.hint()
(-2123).hint()
//如果一个类型预遵从了协议,可以直接拓展协议
struct Lesson {
var name : String
var description : String {
return "课程名是: " + name
}
}
1.description
extension Lesson : CustomStringConvertible {}
//扩展约束:可以在扩展协议的同时,加上限定条件,where语句
extension ShowHint where Self:CustomStringConvertible {
func hint2() -> String {
return "我是一个能显示成字符串的类型" + self.description
}
}
1.hint2()
//集合类型 Collection 也是一种协议,Iterator.Element指代其中的元素
let array = [1,2,3,4]
print(array)
extension Collection where Iterator.Element : CustomStringConvertible {
func newDesc() -> String {
let itemAsText = self.map { $0.description}
return "该集合类型元素数目是\(self.count),元素的值是" + itemAsText.joined(separator: ",")
}
}
array.newDesc()
print(array)
----协议的集合类型-----
//协议的集合类型:因为协议可以作为类型使用,可把遵从相同协议的实例放到一个协议类型的数组
let array1 : [CustomStringConvertible] = [1,2,3,"haha"] //as [Any]
for i in array1 {
print(i)
}
----协议继承和默认实现-----
协议继承:一个协议可以继承若干个协议,并可以在继承基础上添加新需求,与class继承类似,区别是class不能多重继承,对结构体进行协议扩展,相当于实现了多重继承(面向协议编程)
//继承的多个协议间用逗号分隔
protocol MyPrintable : CustomStringConvertible,CustomPlaygroundQuickLookable {
}
struct MyContent {
var text : String
var mycustomtext : String
}
//提供默认实现:可以给协议扩展提供一个默认的实现,任何遵从此协议的类型都会获得
extension MyPrintable {
var customPlaygroundQuickLook: PlaygroundQuickLook {
return PlaygroundQuickLook.text("Playground的默认预览文字")
}
}
extension MyContent : MyPrintable {
var description: String {
return self.text
}
// var customPlaygroundQuickLook: PlaygroundQuickLook {
// return PlaygroundQuickLook.text(self.mycustomtext)
// }
}
let mycontent1 = MyContent(text: "内容", mycustomtext: "保留文字")
mycontent1.description
----类专用协议-----
类专用协议:可以把协议限制在class类型(让结构体和枚举无法使用),加关键字class到协议继承列表的第一位
protocol OnlyforClass : class {
}
class MyText : OnlyforClass {
var desc : String {
return "a"
}
}
/*
struct MyStruct : OnlyforClass {
//报错
}
*/
----协议组合-----
协议组合:多个协议临时组合在一起的类型,形式:协议1 & 协议2 &...>
protocol Ageable {
var age : Int {get}
}
protocol Nameable {
var name : String {get}
}
struct Student : Ageable,Nameable {
var age: Int
var name: String
}
struct Teacher : Ageable,Nameable {
var age: Int
var name: String
var title : String
}
func wish(someone: Ageable & Nameable) {
print("祝",someone.name,someone.age,"岁生日快乐!!!")
}
let student1 = Student(age: 10, name: "Tom")
let teacher1 = Teacher(age: 40, name: "Bob", title: "professor")
wish(someone: student1)
wish(someone: teacher1)
----协议检查和转换-----
协议检查和转换:使用is和as类型转换操作符来检查协议遵守与否,或转换成特定的协议
protocol Slogan {
var desc : String {get}
}
protocol Coder : Slogan {
var name : String {get}
}
struct JavaCoder : Coder {
var name: String
var desc: String {
return "我会java,我很牛"
}
}
struct JSCoder : Coder {
var name: String
var desc: String {
return "我会js,我很潮"
}
}
struct Newbie {
var name : String
}
let java1 = JavaCoder(name: "小慕")
let js1 = JSCoder (name: "小课")
let newbie1 = Newbie(name: "小波")
let coders = [java1,js1,newbie1] as [Any]
for coder in coders {
if let coder = coder as? Coder {
print(coder.name,coder.desc)
} else {
print("你不是一个程序员")
}
if let newbie = coder as? Newbie {
print(newbie.name,"你是一个菜鸟")
}
}