In Swift, the protocol can not only define methods and properties, but also the protocol can be extended, the most important is that in the extension of the protocol can be added to some of the default implementation of the method, that is, in the method of the protocol can implement some logic, because of this feature, Swift can be protocol-oriented programming.
Extended protocols and default implementations
protocol Record {var wins:int{Get} var losses:int{Get} func winningpercent ()-Double}structbasketballrecord:record,customstringconvertible {var wins:int var losses:int func winningpercent ()
-Double {returnDouble (WINS)/double (WINS +losses)} var description:string {returnString.init (format:"WINS:%d, losses:%d", [wins,losses])}}structbaseballrecord:record,customstringconvertible {var wins:int var losses:int func winningpercent () -Double {returnDouble (WINS)/double (WINS +losses)} var description:string {returnString.init (format:"WINS:%d, losses:%d", [wins,losses])}} Let Teamrecord= Basketballrecord (Wins:2, Losses:Ten) print (Teamrecord) let baseball= Baseballrecord (Wins:3, Losses:Ten) Print (baseball)
We can see that both structures inherit the record and the customstringconvertible protocol, the first of which is our custom protocol, the second is the system protocol, and the Protocol in Swift can be inherited, So we can rewrite the pattern below.
protocol record:customstringconvertible {var wins:int{Get} var losses:int{Get} func winningpercent ()-Double}structBasketballrecord:record {var wins:int var losses:int func winningpercent ()-Double {returnDouble (WINS)/double (WINS +losses)} var description:string {returnString.init (format:"WINS:%d, losses:%d", [wins,losses])}}structBaseballrecord:record {var wins:int var losses:int func winningpercent ()-Double {returnDouble (WINS)/double (WINS +losses)} var description:string {returnString.init (format:"WINS:%d, losses:%d", [wins,losses])}}
You will see that there is still redundant code that is the same as the customstringconvertible Protocol Implementation of the description return, this time we are like further encapsulation, then what should we do? This actually uses what we say: The protocol can be extended, and the properties and methods of the protocol in the extension can be implemented by default, we can write:
protocol record:customstringconvertible {var wins:int{Get} var losses:int{Get} func winningpercent ()-Double}//Extended Protocolextension Record {var description:string {returnString.init (format:"WINS:%d, losses:%d", [wins,losses])}}structBasketballrecord:record {var wins:int var losses:int func winningpercent ()-Double {returnDouble (WINS)/double (WINS +losses)} }structBaseballrecord:record {var wins:int var losses:int func winningpercent ()-Double {returnDouble (WINS)/double (WINS +losses)}}
Is it much more convenient to write this, but to look closely at the structure of our Compliance agreement is not logical similar, but written several times of the code, we can also consider the method of calculating winning probability also migrated to the extension?
protocol Record:customstringconvertible {var wins:int {Get} var losses:int {Get} }//Extended Protocolextension Record {var description:string {returnString.init (format:"wins:%d, losses:%d", [wins,losses])} var gameplayed:int {returnWINS +Losses} func winningpercent ()-Double {returnDouble (WINS)/Double (gameplayed)}}structBasketballrecord:record {var wins:int var losses:int}structBaseballrecord:record {var wins:int var losses:int}
is not more convenient, then if a game has both winning and losing, and when it is flat, we add a new protocol, when the different protocols, they execute the default method, is both to meet the win-lose and can be flattened inside the method of the default implementation of the extension, if only to comply with a record protocol, The default implementation in the extended record is executed.
protocol Record:customstringconvertible {var wins:int {Get} var losses:int {Get} }//a flat agreementprotocol Tieable {var ties:int {Get Set}}//The extension follows the record agreement and complies with the Tieable protocol .Extension RecordwhereSelf:tieable {var gameplayed:int {returnWINS + losses +Ties} func winningpercent ()-Double {returnDouble (WINS)/Double (gameplayed)}}//Extended Protocolextension Record {var description:string {returnString.init (format:"wins:%d, losses:%d", [wins,losses])} var gameplayed:int {returnWINS +Losses} func winningpercent ()-Double {returnDouble (WINS)/Double (gameplayed)}}structBasketballrecord:record {var wins:int var losses:int}structBaseballrecord:record {var wins:int var losses:int}//we can draw.structfootballrecord:record,tieable {var wins:int var losses:int var ties:int}
Protocol Aggregation
Grammatical structure
Agreement 1 & Agreement 2
Sample code
// Protocol Prizable {func isprizable () -> Bool}func award (prizable:prizable & customstringconvertible) { if " Span style= "COLOR: #000000" > prizable.isprizable () {print (prizable) print ( " You can win the prize " )} else {PR Int ( " You are not allowed to win the prize "
The parameters that represent this function are in compliance with the prizable protocol and the customstringconvertible protocol.
Generic constraints
structstudent:customstringconvertible,equatable,comparable,prizable{var name:string var score:int var description : String {returnname} func isprizable ()-Bool {returnScore > -}}func= = (s1:student,s2:student)Bool {returnS1.score = =S2.score}func< (s1:student,s2:student)Bool {returnS1.score <S2.score}let Tian= Student (Name:"Tian", Score: -) Let a= Student (Name:"Alice", Score: the) Let B= Student (Name:"Bob", Score: the) Let C= Student (Name:"Karl", Score: the) Let students=[a,b,c,tian]//error reason is because comparable this protocol in the implementation of their own call themselves at this time this protocol can not be used as a type in this case we can change to the following code func Topone (Seq:[comparable]) -comparable {}
In order to solve the above error, we can write this
structstudent:customstringconvertible,equatable,comparable,prizable{var name:string var score:int var description : String {returnname} func isprizable ()-Bool {returnScore > -}}func= = (s1:student,s2:student)Bool {returnS1.score = =S2.score}func< (s1:student,s2:student)Bool {returnS1.score <S2.score}let Tian= Student (Name:"Tian", Score: -) Let a= Student (Name:"Alice", Score: the) Let B= Student (Name:"Bob", Score: the) Let C= Student (Name:"Karl", Score: the) Let students=[A,b,c,tian]func Topone<T:Comparable> (Seq:[t])T {assert (Seq.count>0) returnSeq.reduce (seq[0]) {max ($0, $1)}}topone (seq: [4,5,7,8]) func topprizableone<t:comparable & Prizable> (seq:[t])->t? { returnSeq.reduce (nil) {(Temptop:t?, Contender:t)inchguard Contender.isprizable ()Else { returnTemptop} guard let Temptop= TemptopElse { returncontender}returnMax (Temptop, contender)}} Topprizableone (seq:students)?. Name
Swift Learning Notes (protocol-oriented programming)