您的位置:首页 > 移动开发 > Swift

iOS --- 面向协议的编程(swift2.3)

2016-07-04 14:28 537 查看

iOS — 面向协议的编程(swift)

下面简单的介绍面向协议的编程的应用

扩展协议和默认实现

面向协议编程

协议聚合

泛型约束

swift是面向协议的编程语言

UIKit中的委托模式

创建自己的委托模式

可选的协议方法

一:扩展协议和默认实现

protocol Record: CustomStringConvertible{

var wins: Int {get}
var losses: Int {get}

func winningPercent() -> Double
}

// 扩展一个协议的时候,可以拥有实现!,那么就是说,虽然协议不能够实现属性和方法,但是在协议的扩展里面可以实现属性和方法
extension Record{
//那么遵守CustomStringConvertible协议必须实现的属性就可以写在协议的扩展里面,那么结构体和类中就可以不写,打印出来的结果就是自定义的格式
//这个例子就是告诉我们,在协议的扩展中,可以实现属性和函数的逻辑,在类和结构中就不需要实现了
var description: String{
return String(format: "WINS: %d , LOSSES: %d", arguments: [wins,losses])
}

func shoutWins(){
print("WE WIN",wins,"TIMES!!!")
}

var gamePlayed: Int{
return wins + losses
}
}

struct BasketballRecord: Record{

var wins: Int
var losses: Int

func winningPercent() -> Double {
//return Double(wins)/Double(wins + losses)
return Double(wins)/Double(gamePlayed)
}
}
//extension BasketballRecord: CustomStringConvertible{}

struct BaseballRecord: Record{

var wins: Int
var losses: Int

func winningPercent() -> Double {
return Double(wins)/Double(gamePlayed)
}
}

let teamRecord = BasketballRecord(wins: 2, losses: 10)
print(teamRecord)

teamRecord.shoutWins()

// 扩展标准库中的协议
extension CustomStringConvertible{
var descriptionWithDate: String{
return NSDate().description + " " + description
}
}

print( teamRecord.descriptionWithDate )


二:面向协议编程

protocol Record: CustomStringConvertible{

var wins: Int {get}
var losses: Int {get}

//func winningPercent() -> Double
}

extension Record{

var description: String{
return String(format: "WINS: %d , LOSSES: %d", arguments: [wins,losses])
}

var gamePlayed: Int{
return wins + losses
}
}

protocol Tieable{
var ties: Int{get set}
}

//由于有些比赛没有平局,那么我只想给有平局的结构和类增加一个协议的扩张,用where关键字,表示如果这个类或者结构遵守了Tieable协议的话,我就给他扩展这个平局的属性,然后再将gamePlayed和winningPercent的实施细则重写,覆盖在协议中默认的内容,那么如果,我们类或结构遵守了Tieable这个协议的话,我们就可以直接使用这个被覆盖的gamePlayed属性和winningPercent方法了
extension Record where Self: Tieable{

var gamePlayed: Int{
return wins + losses + ties
}

func winningPercent() -> Double {
return Double(wins)/Double(wins + losses + ties)
}
}

struct BasketballRecord: Record{

var wins: Int
var losses: Int

//    func winningPercent() -> Double {
//        return Double(wins)/Double(gamePlayed)
//    }
}

//由于在Record协议里面有一个默认的gamePlayed属性实现过程,但是在我们的具体的结构和类中,可以重写这个属性的实现,也就是可以覆盖协议扩展中属性的实现过程
struct BaseballRecord: Record{

var wins: Int
var losses: Int
let gamePlayed = 162

//    func winningPercent() -> Double {
//        return Double(wins)/Double(gamePlayed)
//    }
}

struct FootballRecord: Record, Tieable{
var wins: Int
var losses: Int
var ties: Int

//    var gamePlayed: Int{
//        return wins + losses + ties
//    }
//
//    func winningPercent() -> Double {
//        return Double(wins)/Double(wins+losses+ties)
//    }
}

let basketballTeamRecord = BasketballRecord(wins: 2, losses: 10)
let baseballTeamRecord = BaseballRecord(wins: 10, losses: 5)

basketballTeamRecord.gamePlayed
baseballTeamRecord.gamePlayed

let footballTeamRecord = FootballRecord(wins: 1, losses: 1, ties: 1)
footballTeamRecord.gamePlayed
footballTeamRecord.winningPercent()


三:协议聚合

protocol Record: CustomStringConvertible{

var wins: Int {get}
var losses: Int {get}
}

extension Record{

var description: String{
return String(format: "WINS: %d , LOSSES: %d", arguments: [wins,losses])
}

var gamePlayed: Int{
return wins + losses
}

func winningPercent() -> Double {
return Double(wins)/Double(gamePlayed)
}
}

protocol Tieable {
var ties: Int {get set}
}

extension Record where Self: Tieable{

var gamePlayed: Int{
return wins + losses + ties
}

func winningPercent() -> Double {
return Double(wins)/Double(wins + losses + ties)
}
}

protocol Prizable{

func isPrizable() -> Bool
}

struct BasketballRecord: Record, Prizable{

var wins: Int
var losses: Int

func isPrizable() -> Bool{
return wins > 2
}
}

struct BaseballRecord: Record, Prizable{

var wins: Int
var losses: Int
let gamePlayed = 162

func isPrizable() -> Bool{
return gamePlayed > 10 && winningPercent() >= 0.5
}
}

struct FootballRecord: Record, Tieable, Prizable{
var wins: Int
var losses: Int
var ties: Int

func isPrizable() -> Bool{
return wins > 1
}
}

var basketballTeamRecord = BasketballRecord(wins: 2, losses: 10)
var baseballTeamRecord = BaseballRecord(wins: 10, losses: 5)
var footballTeamRecord = FootballRecord(wins: 1, losses: 1, ties: 1)

//这里表面传递进来的one不仅要遵守Prizable协议还要遵守CustomStringConvertible协议
func award(one: protocol<CustomStringConvertible, Prizable>){

if one.isPrizable(){
print(one)
print("Congratulation! You won a prize!")
}
else{
print(one)
print("You can not have the prize!")
}
}

award(baseballTeamRecord)

struct Student: CustomStringConvertible, Prizable{//description是CustomStringConvertible必须实现的属性
var name: String
var score: Int
var description: String{
return name
}

func isPrizable() -> Bool {
return score >= 60
}
}

let liuyubobobo = Student(name: "liuyubobobo", score: 100)
award(liuyubobobo)


四:泛型约束

protocol Prizable{
func isPrizable() -> Bool
}

struct Student: CustomStringConvertible, Equatable, Comparable, Prizable{
var name: String
var score: Int
var description: String{
return name + "Score: " + String(score)
}

func isPrizable() -> Bool {
return score >= 60
}
}
func ==(s1:Student,s2:Student) -> Bool{ return s1.score == s2.score}
func <(s1:Student,s2:Student) -> Bool{ return s1.score < s2.score}

let liuyubobobo = Student(name: "liuyubobobo", score: 100)

let a = Student(name: "Alice", score: 80)
let b = Student(name: "Bob", score: 92)
let c = Student(name: "Karl", score: 85)

let students = [a, b, c, liuyubobobo]

//func topOne(seq:[Comparable]) -> Comparable
//让大写的遵守Comparable协议,让数组元素的类型为T,<T: Comparable>就是泛型的约束,,
func topOne<T: Comparable>(seq:[T]) -> T{
assert(seq.count > 0)
//如果使数组中的元素压缩成一个元素,使用结尾闭包
return seq.reduce(seq[0]){ max( $0 , $1 ) }
}

topOne([4,5,7,2])
topOne(["Hello","Swift"])
topOne([a,b,c,liuyubobobo])

//让大写的遵守Comparable协议,让数组元素的类型为T,<T: protocol<Comparable, Prizable>>就是协议聚合的泛型约束,,
func topPrizableOne<T: protocol<Comparable, Prizable>>(seq:[T]) -> T?{
return seq.reduce(nil){ ( tmpTop: T? , contender: T) in

guard contender.isPrizable() else{
return tmpTop
}

guard let tmpTop = tmpTop else{
return contender
}

return max( tmpTop , contender )
}
}

topPrizableOne(students)?.name


五:swift是面向协议的编程语言

/**
根据swift语言中标准库的统计:
Classes: 6 个

Enum: 8 个

Structs: 103 个

Protocol: 86 个

*/

var a: Int = 3

var arr: Array<Int> = [1,2,3]


六:UIKit中的委托模式

这个例子用uitableview引出


七:创建自己的委托模式

protocol TurnBasedGameDelegate{

func gameStart()
func playerMove()
func gameEnd()

func gameOver() -> Bool
}

protocol TurnBasedGame{

var turn: Int{get set}

func play()
}

//这个类完成了整个游戏的过程,但是不知道游戏的细节部分,那么在具体的玩这个游戏的时候,我们就不要担心这个游戏到底是怎么一个过程,只是说明这个游戏怎么玩就是了
class SinglePlayerTurnBasedGame: TurnBasedGame{

var delegate:TurnBasedGameDelegate!
var turn = 0

func play(){

delegate.gameStart()//游戏开始
while !delegate.gameOver() {//知道什么时候结束
print("ROUND",turn,":")
delegate.playerMove()//玩家开始动作
turn += 1
}
delegate.gameEnd()
}
}

class RollNumberGame: SinglePlayerTurnBasedGame, TurnBasedGameDelegate{

var score = 0

override init() {
super.init()//先调用父类的构造函数,初始化父类的属性
delegate = self//再初始化自己属性
}

func gameStart() {

score = 0
turn = 0

print("Welcome to Roll Number Game.")
print("Try to use least turn to make total 100 scores!")
}

func playerMove() {
let rollNumber = Int(arc4random())%6 + 1
score += rollNumber
print("You rolled a" , rollNumber , "! The score is",score,"now!")
}

func gameEnd() {
print("Congratulation! You win the game in" , turn , "ROUND!")
}

func gameOver() -> Bool{
return score >= 30
}
}

let rollingNumber = RollNumberGame()
rollingNumber.play()

class RockPaperScissors: SinglePlayerTurnBasedGame, TurnBasedGameDelegate{

enum Shape: Int, CustomStringConvertible{
case Rock
case Scissors
case Papper

func beat(shape: Shape) -> Bool{
return (self.rawValue + 1)%3 == shape.rawValue
}

var description: String{

switch(self){
case .Papper:   return "Paper"
case .Rock:     return "Rock"
case .Scissors: return "Scissors"
}
}
}

var wins = 0
var otherWins = 0

override init() {
super.init()
delegate = self
}

static func go() -> Shape{
return Shape(rawValue: Int(arc4random())%3)!
}

func gameStart() {
wins = 0
otherWins = 0
print("== Rock Paper Scissor ==")
}

func gameOver() -> Bool {
//return turn >= 3
return wins >= 2 || otherWins >= 2
}

func gameEnd() {
if( wins >= 2 ){
print("YOU WIN!")
}
else{
print("YOU LOSE...")
}
}

func playerMove() {

let yourShape = RockPaperScissors.go()
let otherShape = RockPaperScissors.go()
print("Your:",yourShape)
print("Other:",otherShape)

if yourShape.beat(otherShape){
print("You win this round")
wins += 1
}
else if otherShape.beat(yourShape){
print("You lose this round")
otherWins += 1
}
else{
print("Tie in this round")
}
}

}

let rockPaperScissors = RockPaperScissors()
rockPaperScissors.play()


八:可选的协议方法

//如果协议中有可选型的方法,那么在协议前必须加上@objc关键字,那么这个协议就能被OC语言应用
@objc protocol TurnBasedGameDelegate{

func gameStart()
func playerMove()
func gameEnd()

optional func turnStart()
optional func turnEnd()

func gameOver() -> Bool
}

protocol TurnBasedGame{

var turn: Int{get set}

func play()
}
//那么这个父类也要继承object-c
class SinglePlayerTurnBasedGame: NSObject, TurnBasedGame{

var delegate:TurnBasedGameDelegate!
var turn = 0

func play(){

delegate.gameStart()
while !delegate.gameOver() {
//如果一个函数是可选型的函数,那么这个函数就要解包
if let turnStart = delegate.turnStart{
turnStart()
}
else{
print("Round",turn,":")
}

delegate.playerMove()

//这里也需要解包,如果解包成功了就调用这个函数,如果解包失败就什么事也不做
delegate.turnEnd?()

turn += 1
}
delegate.gameEnd()
}
}

class RockPaperScissors: SinglePlayerTurnBasedGame, TurnBasedGameDelegate{

enum Shape: Int, CustomStringConvertible{
case Rock
case Scissors
case Papper

func beat(shape: Shape) -> Bool{
return (self.rawValue + 1)%3 == shape.rawValue
}

var description: String{

switch(self){
case .Papper:   return "Paper"
case .Rock:     return "Rock"
case .Scissors: return "Scissors"
}
}
}

var wins = 0
var otherWins = 0

override init() {
super.init()
delegate = self
}

static func go() -> Shape{
return Shape(rawValue: Int(arc4random())%3)!
}

@objc func gameStart() {//
wins = 0
otherWins = 0
print("== Rock Paper Scissor ==")
}

func gameOver() -> Bool {
return wins >= 2 || otherWins >= 2
}

func gameEnd() {
if( wins >= 2 ){
print("YOU WIN!")
}
else{
print("YOU LOSE...")
}
}

func playerMove() {

let yourShape = RockPaperScissors.go()
let otherShape = RockPaperScissors.go()
print("Your:",yourShape)
print("Other:",otherShape)

if yourShape.beat(otherShape){
print("You win this round")
wins += 1
}
else if otherShape.beat(yourShape){
print("You lose this round")
otherWins += 1
}
else{
print("Tie in this round")
}
}

func turnStart() {
print("*** ROUND START ***")
}

func turnEnd(){
print("*******************")
}

}

let rockPaperScissors = RockPaperScissors()
rockPaperScissors.play()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: