如果類的所有方法都是抽象的,在Swift和Object-C中稱為協定,在Java語言中稱為接口,在C++中稱為純虛類;隻有方法的定義沒有方法的具體實作,所在的類叫抽象類
協定不能被執行個體化
Swift和Object-C中實作抽象類的過程稱為遵守協定
一、聲明和遵守協定
類、結構體和枚舉類型可以聲明與遵守某個協定,并提供該協定所需要的屬性和方法
協定定義的文法如下:
protocol 協定名 {
//内容
}
在聲明遵守協定時,格式如下:
類型 類型名:協定1,協定2 {
//遵守協定内容
類型包括類、結構體和枚舉,冒号後面是遵守的協定,如果有多個協定,協定之間用逗号隔開
協定可以要求其遵守者提供執行個體屬性,靜态屬性,執行個體方法和靜态方法的實作,
二、協定方法
協定可以要求其遵守者實作某些指定方法,包括執行個體方法和靜态方法,這些方法在協定中被定義,協定方法和普通方法類似,但不支援邊長參數和預設值參數,也不需要大括号和方法體
1、執行個體協定方法
protocol Figure {
func onDraw()
}
class Rectangle:Figure {
func onDraw(){
println("繪制矩形")
}
}
class Circle:Figure {
func onDraw(){
println("繪制圓形")
}
}
2、靜态協定方法
在協定中定義靜态方法與在類中定義靜态方法一樣,方法前需要添加class關鍵字,在遵守該協定的時候,遵守者靜态方法前加class或者static,與遵守者類型有有關系,如果是類,關鍵字就是class,如果是結構體或枚舉,關鍵字就是static.
protocol Account {
class func interestBy(amount:Double)->Double
}
class ClassImp:Account {
class func interestBy(amount:Double)->Double {
return 0.668 * amount
}
}
class StructImp:Account {
static func interestBy(){
return 0.668 * amount
}
}
3、變異方法
在結構體和枚舉類型中可以定義變異方法,而在類中沒有這種方法,原因是結構體和枚舉中的屬性是不可修改,通過定義變異方法,可以修改這些屬性,而類是引用類型,不需要變種方法就可以修改自己的屬性;
在協定定義變種方法時,方法前要加上mutating關鍵字,類、結構體和枚舉都可以實作變異方法,類實作變異方法時,前面不需要加mutating關鍵字,結構體和枚舉在實作變異方法時,前面需要加mutating關鍵字
protocol Editable {
mutating func edit()
}
class ClassImp:Editable{
var name = "ClassImp"
func edit(){
println("編輯ClassImp...")
self.name = "編輯ClassImp"
}
}
struct StructImp:Editable {
var name = "StructImp"
mutating func edit(){
println("編輯StructImp")
self.name = "編輯StructImp"
}
}
struct Enum:Editable {
case Monday
case Tuesday
case Wednesday
case Thursday
case Friday
mutating func edit(){
self = .Friday
}
}
4、執行個體協定屬性
協定可以要求其遵守者實作某些指定屬性,包括執行個體屬性和靜态屬性,在具體定義的時候,每一種屬性都可以有隻讀和讀寫之分
對于遵守者而言,執行個體屬性時市場靈活的,無論是存儲屬性還是計算屬性,隻要能通過協定屬性的要求,就可以通過編譯,甚至是協定中定義了隻讀屬性,而遵守者提供了對該屬性的讀寫,這也是被允許的,因為遵守者通過了協定的隻讀屬性要求,協定隻規定了必須要做的事情,但沒有規定不能做的事情;
protocol Person {
var firstName:String{get set}
var lastName:String {get set}
var fullName:String{get}
}
class Employee:Person {
var no:Int = 0
var job:String?
var salary:Double = 0
var firstName:String = "Tony"
var lastName:String = "zhang"
var fullName:String {
get {
return "\(firstName)\(lastName))"
}
set(newFullName){
var name = newFullName.componentsSeperatedByString(".")
self.firstName=name[0]
self.lastName=name[1]
}
}
}
三、協定屬性
在協定中定義靜态屬性與在協定中定義靜态屬性類型,屬性前面要加class關鍵字還是static,與遵守者類型有關系,如果是類,關鍵字是class,如果是結構體和枚舉,關鍵字是static
protocol Account {
class var interestRate:Double {get}
class func interestBy(amount:Double)->Double
}
class ClassImp:Account{
class var interestRate:Double {
return 0.668
}
class func interestBy(amount:Double)->Double{
return ClassImp.interestRate * amount
}
}
struct StructImp:Account {
static var interestRate:Double = 0.668
static func interestBy(amount:Double)->Double {
return StructImp.interestRate * amount
}
}
四、把協定作為類型使用
雖然協定沒有具體的實作代碼,不能被執行個體化,但它的存在是為了規範其遵守者而設計的,它是面向接口程式設計必不可少的機制,面向接口程式設計的系統的定義與實作應該分離,協定作為資料類型暴露給使用者,使其不用關心具體的實作細節,進而提供系統的擴充性和複用性;
在Swift中,協定作為資料類型使用,它可以出現在任意允許資料類型出現的地方:
protocol Person {
var firstName:String{get set}
var lastName:String {get set}
var fullName:String{get}
fun description()->String
}
class Student:Person {
var school:String
var firstName:String
var lastName:String
var fullName:String {
return self.firstName + self.lastName
}
func description()->String {
return self.firstName+self.lastName+self.school
}
init(firstName:String,lastName:String,school:String){
self.firstName = firstName
self.lastName = lastName
self.schooll = school
}
}
五、協定的繼承
一個協定繼承就像是類繼承一樣:
protocol Person {
var firstName:String{get set}
var lastName:String {get set}
var fullName:String{get}
fun description()->String
}
protocol Student:Person {
var school:String
}
class Graduate:Student{
}
六、協定的合成
protocol Ship {
var displacement:Double {get set}
}
protocol Weapon {
var gunNumber{get set}
}
class WarShip:Ship,Weapon{
var displacement = 100000.00
var gunNumber = 10
}
func showWarResource(resource:protocol<Ship,Weapon>){
println("\(resource.displacement):\(resource.gunNumber)")
}
let ship = WarShip()
showWarResource(ship)