Swift--协议--10

----协议的定义----

//协议:方法,属性或一段功能的蓝本
//协议可被类,结构体和枚举“领养”从而“长大成人”
//任何满足协议的“需求”的类型,被称为“遵从”该协议

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,"你是一个菜鸟")
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容