----協(xié)議的定義----
//協(xié)議:方法萤捆,屬性或一段功能的藍本
//協(xié)議可被類恩伺,結(jié)構(gòu)體和枚舉“領(lǐng)養(yǎng)”從而“長大成人”
//任何滿足協(xié)議的“需求”的類型堤器,被稱為“遵從”該協(xié)議
protocol APro {
}
protocol BPro {
}
//領(lǐng)養(yǎng)/遵從若干個協(xié)議川蒙,用逗號分隔
struct AStruct : APro,BPro {
}
//超類在協(xié)議之前
class Name {
}
class GiveName:Name,APro,BPro {
}
----屬性協(xié)議----
屬性協(xié)議:顧名思義庙睡,要求遵從實現(xiàn)已制定的名稱實現(xiàn)屬性,但具體實現(xiàn)是實例屬性或類型屬性并不關(guān)心
//可以指定要求實現(xiàn)getter和setter+getter揪漩,屬性必須定義為變量 var
protocol FileAccessPriority {
var readOnly : Bool { get }
var readWrite : Bool { get set}
}
protocol AccessUrl {
static var link:String {get}
}
//遵從實例屬性協(xié)議 例子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
//遵從實例屬性協(xié)議 例子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
----屬性協(xié)議----
方法協(xié)議:定義使沒有{}執(zhí)行體,實現(xiàn)僅要求名稱相同
作用:可以讓一個類/結(jié)構(gòu)體/枚舉的方法吏口,分解為更小的組合奄容,從而更加靈活性
//類型方法協(xié)議:前綴總是static
protocol AMethod {
static func foo()
}
class A :AMethod {
class func foo() {
print("哈哈哈")
}
}
A.foo()
//實例方法協(xié)議
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()
//結(jié)構(gòu)體冰更,枚舉的 “變異方法協(xié)議”
protocol Switchable {
mutating func onOff()
}
enum MySwitch : Switchable {
mutating func onOff() {
switch self {
case .off:
self = .on
default:
self = .off
}
}
case on,off
}
----構(gòu)造方法協(xié)議----
構(gòu)造方法協(xié)議:可以要求遵從者實現(xiàn)指定的構(gòu)造方法
實現(xiàn)時用required init,編譯器會提示添加昂勒,無需手動添加required
protocol AA {
init(a:Int)
}
struct B : AA {
init(a : Int) {
}
}
class C : AA {
required init(a: Int) {
}
}
//協(xié)議作為類型使用: 可用于參數(shù)類型/返回類型蜀细; 變量/常量/屬性 ;集合類型中的元素類型
//實例方法協(xié)議
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())
----協(xié)議作為代理----
協(xié)議作為代理:代理是一種常見的設(shè)計模式戈盈,可以讓類或結(jié)構(gòu)體把一部分職責奠衔,指派給非同類的實例去承擔
/*
1.若要尋求代理,可以通過定義一個協(xié)議塘娶,打包要實現(xiàn)的職責于其中
2.該代理協(xié)議的遵從者就可以實現(xiàn)這些打包的職責
3.代理在IOS開發(fā)中归斤,一般可以用于響應(yīng)特定的操作,或從外部數(shù)據(jù)源取回數(shù)據(jù)但無需了解是何種數(shù)據(jù)源
*/
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,"開啟游戲刁岸,獲得經(jīng)驗脏里,2000")
return 2000
}
func rolePK(with player: Player, armed: Bool) -> Int {
if armed {
print(player.role.name, "PK 開始,有武器虹曙,獲得5000經(jīng)驗")
return 5000
} else {
print(player.role.name, "PK 開始迫横,沒有武器,獲得2500經(jīng)驗")
return 2500
}
}
func end(with player: Player) -> Int {
print(player.role.name, "正常退出酝碳,獲得1000經(jīng)驗")
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()
----協(xié)議擴展和約束-----
//協(xié)議擴展:即使無源碼權(quán)限下,給已有的類添加協(xié)議
//即存實例會自動遵從添加了的協(xié)議
let a = 1
protocol ShowHint {
func hint() -> String
}
extension Int : ShowHint {
func hint() -> String {
return "整數(shù):\(self)"
}
}
a.hint()
(-2123).hint()
//如果一個類型預(yù)遵從了協(xié)議疏哗,可以直接拓展協(xié)議
struct Lesson {
var name : String
var description : String {
return "課程名是: " + name
}
}
1.description
extension Lesson : CustomStringConvertible {}
//擴展約束:可以在擴展協(xié)議的同時呛讲,加上限定條件,where語句
extension ShowHint where Self:CustomStringConvertible {
func hint2() -> String {
return "我是一個能顯示成字符串的類型" + self.description
}
}
1.hint2()
//集合類型 Collection 也是一種協(xié)議沃斤,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 "該集合類型元素數(shù)目是\(self.count),元素的值是" + itemAsText.joined(separator: ",")
}
}
array.newDesc()
print(array)
----協(xié)議的集合類型-----
//協(xié)議的集合類型:因為協(xié)議可以作為類型使用圣蝎,可把遵從相同協(xié)議的實例放到一個協(xié)議類型的數(shù)組
let array1 : [CustomStringConvertible] = [1,2,3,"haha"] //as [Any]
for i in array1 {
print(i)
}
----協(xié)議繼承和默認實現(xiàn)-----
協(xié)議繼承:一個協(xié)議可以繼承若干個協(xié)議,并可以在繼承基礎(chǔ)上添加新需求衡瓶,與class繼承類似徘公,區(qū)別是class不能多重繼承,對結(jié)構(gòu)體進行協(xié)議擴展哮针,相當于實現(xiàn)了多重繼承(面向協(xié)議編程)
//繼承的多個協(xié)議間用逗號分隔
protocol MyPrintable : CustomStringConvertible,CustomPlaygroundQuickLookable {
}
struct MyContent {
var text : String
var mycustomtext : String
}
//提供默認實現(xiàn):可以給協(xié)議擴展提供一個默認的實現(xiàn)关面,任何遵從此協(xié)議的類型都會獲得
extension MyPrintable {
var customPlaygroundQuickLook: PlaygroundQuickLook {
return PlaygroundQuickLook.text("Playground的默認預(yù)覽文字")
}
}
extension MyContent : MyPrintable {
var description: String {
return self.text
}
// var customPlaygroundQuickLook: PlaygroundQuickLook {
// return PlaygroundQuickLook.text(self.mycustomtext)
// }
}
let mycontent1 = MyContent(text: "內(nèi)容", mycustomtext: "保留文字")
mycontent1.description
----類專用協(xié)議-----
類專用協(xié)議:可以把協(xié)議限制在class類型(讓結(jié)構(gòu)體和枚舉無法使用),加關(guān)鍵字class到協(xié)議繼承列表的第一位
protocol OnlyforClass : class {
}
class MyText : OnlyforClass {
var desc : String {
return "a"
}
}
/*
struct MyStruct : OnlyforClass {
//報錯
}
*/
----協(xié)議組合-----
協(xié)議組合:多個協(xié)議臨時組合在一起的類型十厢,形式:協(xié)議1 & 協(xié)議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,"歲生日快樂5忍!蛮放!")
}
let student1 = Student(age: 10, name: "Tom")
let teacher1 = Teacher(age: 40, name: "Bob", title: "professor")
wish(someone: student1)
wish(someone: teacher1)
----協(xié)議檢查和轉(zhuǎn)換-----
協(xié)議檢查和轉(zhuǎn)換:使用is和as類型轉(zhuǎn)換操作符來檢查協(xié)議遵守與否,或轉(zhuǎn)換成特定的協(xié)議
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,"你是一個菜鳥")
}
}