array协议 swift
2017-02-25 19:38:00 weixin_34200628 阅读数 30

数组可以存储同一个类型的多个值,而且相同的值可以多次出现在数组中的不同位置。

创建数组

1.定义数据类型有两种形式

var array1: Array<String>
var array2:[String]

2.创建一个空数组
通过初始化函数来创建一个有特定数据类型的空数组

var someInts = [Int]()

3.用字面量构造数组

import UIKit
let array:[String]=["Hello","Hi"]
let array2 = ["zhangsan",18];

4.两个数组相加来创建一个新数组

let array1 = ["张三","李四"];
let array2 = ["王五"]
print(array1+array2)

注意:
数组对于存储数据有着具体的要求,数组元素在被存储进入某个数组之前,必须明确数据类型,方法是通过显式的类型标注或者类型推断。

数组的常见操作

1.获取数组的长度
Array提供了一个count属性,用于获取数组中元素的总个数。
2.数组的遍历

let array = [11,22,33,44,55]
for element in array{
      print(element)
}

3.数组元素的增加、删除

// 定义一个可变数组
var array = ["zhangsan","lisi"]
// 在末尾追加1个元素
array.append("wangwu")
print(array)
// 向指定位置插入1个元素
array.insert("zhaoliu",at:2)
print(array)
// 删除第一个元素
array.removeFirst()
print(array)
// 删除最后一个元素
array.removeLast()
print(array)
// 删除所有的元素
array.removeAll(keepingCapacity:true)
print(array)

4.使用下标语法修改数组元素
使用下标来改变已有索引对应的元素

array[1] = "new"

如果要修改数组中的多个索引对应的元素,可以采用区间的形式表示已经存在的多个索引值。

array[1...2] =["Eight","Nine"]
2016-08-04 22:51:00 weixin_34293141 阅读数 6

协议
与OC中一样,协议的关键字也是protocol
在Swift中,class(类)、struct(结构体)、enum(枚举)都能有协议
但是协议中有个关键字mutating,协议所针对类型不同,对这个关键字的需求也就不同

关键字mutating允许在实例方法中修改对象本身或属性的值
理解:Swift中有三种type(类型):class(类),struct(结构体),enum(枚举)
这三个类型的区别在于class是引用类型,而另外两个是值类型。区别在于,引用类型的对象是可以动态分配的(可以变化),而值类型的对象在初始化时一般就分配好了(不准改动)。而mutating关键字则允许在它修饰的方法中去修改对象本身的值或对象属性的值(self或self.xxx的值)
上述对于mutating关键字的原理解释,如依然不懂就记住:
1.如果协议仅针对class,不需要mutating关键字
2.如果协议会被enum或struct使用,协议中的方法需要mutating修饰

例子1:对class协议

文/Mi欧阳(简书作者)
原文链接:http://www.jianshu.com/p/2fab5d94b879
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

protocol ExProtocol1 {
    var simpleDescription: String {
        get
    }
    func adjust() //省略mutating关键字
}

class SimpleClass: ExProtocol1 {
    var simpleDescription: String = "A very simple class"
    var anotherProperty: Int = 110
    func adjust() {
        //即使不写mutating,也可以改变方法属性
        simpleDescription += " Now 100% adjusted"
    }
}

var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription

例子2:对struct(结构体)协议,协议方法中不改变结构体属性

protocol ExProtocol2 {
    var simpleDescription: String {
        get
    }
    func adjust() //省略mutating关键字
}

struct SimpleStruct: ExProtocol2 {
    var simpleDescription: String = "A simple structure"
    func adjust() {//不加mutating关键字
        let testDescription = simpleDescription + "test SimpleStruct" //不改变对象属性
        print(testDescription)
    }
}

var b = SimpleStruct()
b.adjust()
//b这个对象的属性simpleDescription,值未改变

//例子3:对struct(结构体)协议,在协议方法中改变结构体属性

protocol ExProtocol3 {
    var simpleDescription: String {
        get
    }
    //mutating在这里修饰了,结构体中的对应方法才能使用这个关键字修饰
    mutating func adjust()
}

struct SimpleStruct2: ExProtocol3 {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {//使用mutating关键字
        simpleDescription += "(adjusted)" //允许改变结构体属性
    }
}

var c = SimpleStruct2()
c.adjust()
//c这个对象的属性simpleDescription,值发生了改变
let cDescription = c.simpleDescription

扩展
extension关键字代表扩展
可以使用扩展为一个现有的类型添加函数,比如新的方法和计算属性。

extension Double {
    func absoluteValue() -> Double {
        return self < 0 ? -self : self
        //并不是改变了self,完整代码如下:
        //let a = self < 0 ? -self : self
        //return a
    }
}

print((-3.2).absoluteValue())

Swift中还可以用扩展为一个类型添加协议,并实现协议属性或方法
扩展中的协议(最好的体现mutating的例子)

protocol ExProtocol4 {
    var simpleDescription: String {
        get
    }
    mutating func adjustTest1() //mutating关键字
    func adjustTest2() -> Int //无mutating,返回Int
}

extension Int: ExProtocol4 {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjustTest1(){ //使用mutating关键字
        self += 42//改变了self
    }
    func adjustTest2() -> Int{
        let total = self + 42 //使用self,但不改变
        return total //返回一个临时常量
    }

    func mormalFunc() -> Int { //普通方法
        let zzz = self + 11  //使用方法
        return zzz
    }
}

//使用扩展
7.simpleDescription
//7.adjustTest1()   //不允许这么写,因为对象会发生改变
7.adjustTest2()    //49,这是个临时常量的值
/*
其实7.adjustTest1() 拆开来就是:
let servenLet = 7
servenLet.adjustTest1()
let 声明的是个常量,adjustTest1不能改变一个常量的值。
所以不能用这个方法,把let改成var就行
*/

var serven = 7  //这里值是7
serven.adjustTest1()  //使用该方法变量serven的值会发生改变
serven  //这里值变成了49
serven.adjustTest2()  //输出91,但这是一个临时常量的值

获取协议中的值(协议实例中的值)

//一个类实现了某个协议,我们可以通过如下方法获得协议实例
var protocolValue: ExProtocol4 = serven
//protocolValue的类型是ExProtocol4,可访问协议中的属性
protocolValue.simpleDescription
protocolValue.adjustTest1()//访问协议中的方法
//protocolValue.mormalFunc()  //不属于协议的属性或方法不能访问
2017-03-24 10:19:00 weixin_34184158 阅读数 10

协议的语法

protocol SomeProtocol {
    // protocol definition goes here
}

struct SomeStructure: FirstProtocol, AnotherProtocol {
    // structure definition goes here
}

class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
    // class definition goes here
}

属性要求

// 协议可以要求所有遵循该协议的类型提供特定名字和类型的实例属性或类型属性。协议并不会具体说明属性是储存型属性还是计算型属性——它只具体要求属性有特定的名称和类型。协议同时要求一个属性必须明确是可读的或可读的和可写的

protocol SomeProtocol {
    var mustBeSettable: Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}
protocol AnotherProtocol {
    static var someTypeProperty: Int { get set }
}
protocol FullyNamed {
    var fullName: String { get }
}
struct Person: FullyNamed {
    var fullName: String
}
let john = Person(fullName: "John Appleseed")
// john.fullName is "John Appleseed"
class Starship: FullyNamed {
    var prefix: String?
    var name: String
    init(name: String, prefix: String? = nil) {
        self.name = name
        self.prefix = prefix
    }
    var fullName: String {
        return (prefix != nil ? prefix! + " " : "") + name
    }
}
var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
// ncc1701.fullName is "USS Enterprise"

方法要求

//协议可以要求采纳的类型实现指定的实例方法和类方法。这些方法作为协议定义的一部分,书写方式与正常实例和类方法的方式完全相同,但是不需要大括号和方法的主体。允许变量拥有参数,与正常的方法使用同样的规则。但在协议的定义中,方法参数不能定义默认值。

protocol SomeProtocol {
    static func someTypeMethod()
}
protocol RandomNumberGenerator {
    func random() -> Double
}
class LinearCongruentialGenerator: RandomNumberGenerator {
    var lastRandom = 42.0
    let m = 139968.0
    let a = 3877.0
    let c = 29573.0
    func random() -> Double {
        lastRandom = ((lastRandom * a + c) % m)
        return lastRandom / m
    }
}
let generator = LinearCongruentialGenerator()
print("Here's a random number: \(generator.random())")
// Prints "Here's a random number: 0.37464991998171"
print("And another one: \(generator.random())")
// Prints "And another one: 0.729023776863283"

异变方法要求

protocol Togglable {
    mutating func toggle()
}
enum OnOffSwitch: Togglable {
    case Off, On
    mutating func toggle() {
        switch self {
        case Off:
            self = On
        case On:
            self = Off
        }
    }
}
var lightSwitch = OnOffSwitch.Off
lightSwitch.toggle()
// lightSwitch is now equal to .On

初始化器要求(required)

protocol SomeProtocol {
    init(someParameter: Int)
}
// 你可以通过实现指定初始化器或便捷初始化器来使遵循该协议的类满足协议的初始化器要求。在这两种情况下,你都必须使用 required 关键字修饰初始化器的实现:
class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // initializer implementation goes here
    }
}
// 如果一个子类重写了父类指定的初始化器,并且遵循协议实现了初始化器要求,那么就要为这个初始化器的实现添加 required 和 override 两个修饰符:

protocol SomeProtocol {
    init()
}
 
class SomeSuperClass {
    init() {
        // initializer implementation goes here
    }
}
 
class SomeSubClass: SomeSuperClass, SomeProtocol {
    // "required" from SomeProtocol conformance; "override" from SomeSuperClass
    required override init() {
        // initializer implementation goes here
    }
}

可失败初始化器要求

如同可失败初始化器定义的一样,协议可以为遵循该协议的类型定义可失败的初始化器。

遵循协议的类型可以使用一个可失败的或不可失败的初始化器满足一个可失败的初始化器要求。不可失败初始化器要求可以使用一个不可失败初始化器或隐式展开的可失败初始化器满足。

将协议作为类型

class Dice {
    let sides: Int
    let generator: RandomNumberGenerator
    init(sides: Int, generator: RandomNumberGenerator) {
        self.sides = sides
        self.generator = generator
    }
    func roll() -> Int {
        return Int(generator.random() * Double(sides)) + 1
    }
}
//使用 穿一个遵循协议的对象
var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
for _ in 1...5 {
    print("Random dice roll is \(d6.roll())")
}
// Random dice roll is 3
// Random dice roll is 5
// Random dice roll is 4
// Random dice roll is 5
// Random dice roll is 4

委托 (代理模式)

protocol DiceGame {
    var dice: Dice { get }
    func play()
}
protocol DiceGameDelegate {
    func gameDidStart(_ game: DiceGame)
    func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
    func gameDidEnd(_ game: DiceGame)
}
class SnakesAndLadders: DiceGame {
    let finalSquare = 25
    let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
    var square = 0
    var board: [Int]
    init() {
        board = Array(repeating: 0, count: finalSquare + 1)
        board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
        board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
    }
    var delegate: DiceGameDelegate?
    func play() {
        square = 0
        delegate?.gameDidStart(self)
        gameLoop: while square != finalSquare {
            let diceRoll = dice.roll()
            delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
            switch square + diceRoll {
            case finalSquare:
                break gameLoop
            case let newSquare where newSquare > finalSquare:
                continue gameLoop
            default:
                square += diceRoll
                square += board[square]
            }
        }
        delegate?.gameDidEnd(self)
    }
}
class DiceGameTracker: DiceGameDelegate {
    var numberOfTurns = 0
    func gameDidStart(_ game: DiceGame) {
        numberOfTurns = 0
        if game is SnakesAndLadders {
            print("Started a new game of Snakes and Ladders")
        }
        print("The game is using a \(game.dice.sides)-sided dice")
    }
    func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
        numberOfTurns += 1
        print("Rolled a \(diceRoll)")
    }
    func gameDidEnd(_ game: DiceGame) {
        print("The game lasted for \(numberOfTurns) turns")
    }
}
let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()
// Started a new game of Snakes and Ladders
// The game is using a 6-sided dice
// Rolled a 3
// Rolled a 5
// Rolled a 4
// Rolled a 5
// The game lasted for 4 turns

在扩展里添加协议遵循

protocol TextRepresentable {
    var textualDescription: String { get }
}
extension Dice: TextRepresentable {
    var textualDescription: String {
        return "A \(sides)-sided dice"
    }
}
let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription)
// Prints "A 12-sided dice"
extension SnakesAndLadders: TextRepresentable {
    var textualDescription: String {
        return "A game of Snakes and Ladders with \(finalSquare) squares"
    }
}
print(game.textualDescription)
// Prints "A game of Snakes and Ladders with 25 squares"

使用扩展声明采纳协议

// 注意类型不会因为满足需要就自动采纳协议。它们必须显式地声明采纳了哪个协议。

extension Dice: TextRepresentable {
    var textualDescription: String {
        return "A \(sides)-sided dice"
    }
}
struct Hamster {
    var name: String
    var textualDescription: String {
        return "A hamster named \(name)"
    }
}
extension Hamster: TextRepresentable {}
let simonTheHamster = Hamster(name: "Simon")
let somethingTextRepresentable: TextRepresentable = simonTheHamster
print(somethingTextRepresentable.textualDescription)
// Prints "A hamster named Simon"

协议类型的集合

let things: [TextRepresentable] = [game, d12, simonTheHamster]

for thing in things {
    print(thing.textualDescription)
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon

协议继承

// 协议可以继承一个或者多个其他协议并且可以在它继承的基础之上添加更多要求

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // protocol definition goes here
}
protocol PrettyTextRepresentable: TextRepresentable {
    var prettyTextualDescription: String { get }
}
extension SnakesAndLadders: PrettyTextRepresentable {
    var prettyTextualDescription: String {
        var output = textualDescription + ":\n"
        for index in 1...finalSquare {
            switch board[index] {
            case let ladder where ladder > 0:
                output += "▲ "
            case let snake where snake < 0:
                output += "▼ "
            default:
                output += "○ "
            }
        }
        return output
    }
}
print(game.prettyTextualDescription)
// A game of Snakes and Ladders with 25 squares:
// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○

类专用的协议

//通过添加 class 关键字到协议的继承列表,
//你就可以限制协议只能被类类型采纳(并且不是结构体或者枚举)。
// class 关键字必须出现在协议继承列表的最前边,在任何继承的协议之前:

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

协议组合 (&)

protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) {
    print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
// Prints "Happy birthday, Malcolm, you're 21!"

协议遵循的检查

// 你可以使用类型转换中描述的 is 和 as 运算符来检查协议遵循,
//还能转换为特定的协议。检查和转换协议的语法与检查和转换类型是完全一样的:

protocol HasArea {
    var area: Double { get }
}


class Circle: HasArea {
    let pi = 3.1415927
    var radius: Double
    var area: Double { return pi * radius * radius }
    init(radius: Double) { self.radius = radius }
}
class Country: HasArea {
    var area: Double
    init(area: Double) { self.area = area }
}

class Animal {
    var legs: Int
    init(legs: Int) { self.legs = legs }
}
let objects: [AnyObject] = [
    Circle(radius: 2.0),
    Country(area: 243_610),
    Animal(legs: 4)
]
for object in objects {
    if let objectWithArea = object as? HasArea {
        print("Area is \(objectWithArea.area)")
    } else {
        print("Something that doesn't have an area")
    }
}
// Area is 12.5663708
// Area is 243610.0
// Something that doesn't have an area

可选协议要求 (optional @objc 标志标记 )

// 你可以给协议定义可选要求,这些要求不需要强制遵循协议的类型实现。
// 可选要求使用 optional 修饰符作为前缀放在协议的定义中。可选要求允许你的代码与 Objective-C 操作。
// 协议和可选要求必须使用 @objc 标志标记。
// 注意 @objc 协议只能被继承自 Objective-C 类或其他 @objc 类采纳。它们不能被结构体或者枚举采纳。

@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}
class Counter {
    var count = 0
    var dataSource: CounterDataSource?
    func increment() {
        if let amount = dataSource?.increment?(forCount: count) {
            count += amount
        } else if let amount = dataSource?.fixedIncrement {
            count += amount
        }
    }
}
class ThreeSource: NSObject, CounterDataSource {
    let fixedIncrement = 3
}
var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
    counter.increment()
    print(counter.count)
}

// eg2

@objc class TowardsZeroSource: NSObject, CounterDataSource {
    func increment(forCount count: Int) -> Int {
        if count == 0 {
            return 0
        } else if count < 0 {
            return 1
        } else {
            return -1
        }
    }
}
counter.count = -4
counter.dataSource = TowardsZeroSource()
for _ in 1...5 {
    counter.increment()
    print(counter.count)
}

协议扩展

// 通过给协议创建扩展,所有的遵循类型自动获得这个方法的实现而不需要任何额外的修改。

extension RandomNumberGenerator {
    func randomBool() -> Bool {
        return random() > 0.5
    }
}

let generator = LinearCongruentialGenerator()
print("Here's a random number: \(generator.random())")
// Prints "Here's a random number: 0.37464991998171"
print("And here's a random Boolean: \(generator.randomBool())")
// Prints "And here's a random Boolean: true"
提供默认实现

// 你可以使用协议扩展来给协议的任意方法或者计算属性要求提供默认实现。
// 如果遵循类型给这个协议的要求提供了它自己的实现,那么它就会替代扩展中提供的默认实现

extension PrettyTextRepresentable  {
    var prettyTextualDescription: String {
        return textualDescription
    }
}
给协议扩展添加限制 (where)

// 当你定义一个协议扩展,你可以明确遵循类型必须在扩展的方法和属性可用之前满足的限制。如同 Where 分句(此处应有链接)中描述的那样,在扩展协议名字后边使用 where 分句来写这些限制。比如说,你可以给 Collection 定义一个扩展来应用于任意元素遵循上面 TextRepresentable 协议的集合。

extension Collection where Iterator.Element: TextRepresentable {
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joined(separator: ", ") + "]"
    }
}
let murrayTheHamster = Hamster(name: "Murray")
let morganTheHamster = Hamster(name: "Morgan")
let mauriceTheHamster = Hamster(name: "Maurice")
let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster]
print(hamsters.textualDescription)
// Prints "[A hamster named Murray, A hamster named Morgan, A hamster named Maurice]"
2017-09-21 15:06:12 xiaoxiaobukuang 阅读数 220

协议规定了用来实现某一特定功能所必须的方法和属性。
任意能够满足协议要求的类型被称为遵循(conform)这个协议。
类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能。

语法

协议的语法格式如下:

protocol SomeProtocol {
    // 协议内容
}

要使类遵循某个协议,需要在类型名称后加上协议名称,中间以冒号:分隔,作为类型定义的一部分。遵循多个协议时,各协议之间用逗号,分隔。

struct SomeStructure: FirstProtocol, AnotherProtocol {
    // 结构体内容
}

如果类在遵循协议的同时拥有父类,应该将父类名放在协议名之前,以逗号分隔。

class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
    // 类的内容
}

一、对属性的规定

协议用于指定特定的实例属性或类属性,而不是指定是存储型属性或计算型属性。此外还必须指明是只读的还是可读可写的。
协议中的通常用var来声明变量属性,在类型声明后加上{ set get }来表示属性是可读可写的,只读属性则用{ get }来表示。

protocol classa {

    var marks: Int { get set }
    var result: Bool { get }

    func attendance() -> String
    func markssecured() -> String

}

protocol classb: classa {

    var present: Bool { get set }
    var subject: String { get set }
    var stname: String { get set }

}

class classc: classb {
    var marks = 96
    let result = true
    var present = false
    var subject = "Swift 协议"
    var stname = "Protocols"

    func attendance() -> String {
        return "The \(stname) has secured 99% attendance"
    }

    func markssecured() -> String {
        return "\(stname) has scored \(marks)"
    }
}

let studdet = classc()
studdet.stname = "Swift"
studdet.marks = 98
studdet.markssecured()

print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)

以上程序执行输出结果为:

98
true
false
Swift 协议
Swift

二、对 Mutating 方法的规定

有时需要在方法中改变它的实例。
例如:值类型(结构体,枚举)的实例方法中,将mutating关键字作为函数的前缀,写在func之前,表示可以在该方法中修改它所属的实例及其实例属性的值。

protocol daysofaweek {
    mutating func show()
}

enum days: daysofaweek {
    case sun, mon, tue, wed, thurs, fri, sat
    mutating func show() {
        switch self {
        case .sun:
            self = .sun
            print("Sunday")
        case .mon:
            self = .mon
            print("Monday")
        case .tue:
            self = .tue
            print("Tuesday")
        case .wed:
            self = .wed
            print("Wednesday")
        case .thurs:
            self = .thurs
            print("Wednesday")
        case .fri:
            self = .fri
            print("Wednesday")
        case .sat:
            self = .sat
            print("Saturday")
        default:
            print("NO Such Day")
        }
    }
}

var res = days.wed
res.show()

以上程序执行输出结果为:

Wednesday

三、对构造器的规定

协议可以要求它的遵循者实现指定的构造器。
你可以像书写普通的构造器那样,在协议的定义里写下构造器的声明,但不需要写花括号和构造器的实体,语法如下:

protocol SomeProtocol {
   init(someParameter: Int)
}

实例

protocol tcpprotocol {
   init(aprot: Int)
}

四、协议构造器规定在类中的实现

你可以在遵循该协议的类中实现构造器,并指定其为类的指定构造器或者便利构造器。在这两种情况下,你都必须给构造器实现标上”required”修饰符:

class SomeClass: SomeProtocol {
   required init(someParameter: Int) {
      // 构造器实现
   }
}

protocol tcpprotocol {
   init(aprot: Int)
}

class tcpClass: tcpprotocol {
   required init(aprot: Int) {
   }
}

施用required修饰符可以保证:所有的遵循该协议的子类,同样能为构造器规定提供一个显式的实现或继承实现。
如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同时标示required和override修饰符:

protocol tcpprotocol {
    init(no1: Int)
}

class mainClass {
    var no1: Int // 局部变量
    init(no1: Int) {
        self.no1 = no1 // 初始化
    }
}

class subClass: mainClass, tcpprotocol {
    var no2: Int
    init(no1: Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override"
    required override convenience init(no1: Int)  {
        self.init(no1:no1, no2:0)
    }
}
let res = mainClass(no1: 20)
let show = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(show.no1)")
print("res is: \(show.no2)")

以上程序执行输出结果为:

res is: 20
res is: 30
res is: 50

五、协议类型

尽管协议本身并不实现任何功能,但是协议可以被当做类型来使用。
协议可以像其他普通类型一样使用,使用场景:

  • 作为函数、方法或构造器中的参数类型或返回值类型
  • 作为常量、变量或属性的类型
  • 作为数组、字典或其他容器中的元素类型

实例

protocol Generator {
    associatedtype members
    func next() -> members?
}

var items = [10,20,30].makeIterator()
while let x = items.next() {
    print(x)
}

for lists in [1,2,3].map( {i in i*5}) {
    print(lists)
}

print([100,200,300])
print([1,2,3].map({i in i*10}))

以上程序执行输出结果为:

10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]

六、在扩展中添加协议成员

我们可以可以通过扩展来扩充已存在类型( 类,结构体,枚举等)。
扩展可以为已存在的类型添加属性,方法,下标脚本,协议等成员。

protocol AgeClasificationProtocol {
   var age: Int { get }
   func agetype() -> String
}

class Person {
   let firstname: String
   let lastname: String
   var age: Int
   init(firstname: String, lastname: String) {
      self.firstname = firstname
      self.lastname = lastname
      self.age = 10
   }
}

extension Person : AgeClasificationProtocol {
   func fullname() -> String {
      var c: String
      c = firstname + " " + lastname
      return c
   }

   func agetype() -> String {
      switch age {
      case 0...2:
         return "Baby"
      case 2...12:
         return "Child"
      case 13...19:
         return "Teenager"
      case let x where x > 65:
         return "Elderly"
      default:
         return "Normal"
      }
   }
}

七、协议的继承

协议能够继承一个或多个其他协议,可以在继承的协议基础上增加新的内容要求。
协议的继承语法与类的继承相似,多个被继承的协议间用逗号分隔:

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // 协议定义
}

实例

protocol Classa {
    var no1: Int { get set }
    func calc(sum: Int)
}

protocol Result {
    func print(target: Classa)
}

class Student2: Result {
    func print(target: Classa) {
        target.calc(1)
    }
}

class Classb: Result {
    func print(target: Classa) {
        target.calc(5)
    }
}

class Student: Classa {
    var no1: Int = 10

    func calc(sum: Int) {
        no1 -= sum
        print("学生尝试 \(sum) 次通过")

        if no1 <= 0 {
            print("学生缺席考试")
        }
    }
}

class Player {
    var stmark: Result!

    init(stmark: Result) {
        self.stmark = stmark
    }

    func print(target: Classa) {
        stmark.print(target)
    }
}

var marks = Player(stmark: Student2())
var marksec = Student()

marks.print(marksec)
marks.print(marksec)
marks.print(marksec)
marks.stmark = Classb()
marks.print(marksec)
marks.print(marksec)
marks.print(marksec)

以上程序执行输出结果为:

学生尝试 1 次通过
学生尝试 1 次通过
学生尝试 1 次通过
学生尝试 5 次通过
学生尝试 5 次通过
学生缺席考试
学生尝试 5 次通过
学生缺席考试

八、类专属协议

你可以在协议的继承列表中,通过添加class关键字,限制协议只能适配到类(class)类型。
该class关键字必须是第一个出现在协议的继承列表中,其后,才是其他继承协议。格式如下:

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // 协议定义
}

实例

protocol TcpProtocol {
    init(no1: Int)
}

class MainClass {
    var no1: Int // 局部变量
    init(no1: Int) {
        self.no1 = no1 // 初始化
    }
}

class SubClass: MainClass, TcpProtocol {
    var no2: Int
    init(no1: Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override"
    required override convenience init(no1: Int)  {
        self.init(no1:no1, no2:0)
    }
}

let res = MainClass(no1: 20)
let show = SubClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(show.no1)")
print("res is: \(show.no2)")

以上程序执行输出结果为:

res is: 20
res is: 30
res is: 50

九、协议合成

Swift 支持合成多个协议,这在我们需要同时遵循多个协议时非常有用。
语法格式如下:

protocol Stname {
    var name: String { get }
}

protocol Stage {
    var age: Int { get }
}

struct Person: Stname, Stage {
    var name: String
    var age: Int
}

func show(celebrator: Stname & Stage) {
    print("\(celebrator.name) is \(celebrator.age) years old")
}

let studname = Person(name: "Priya", age: 21)
print(studname)

let stud = Person(name: "Rehan", age: 29)
print(stud)

let student = Person(name: "Roshan", age: 19)
print(student)

以上程序执行输出结果为:

Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)

十、检验协议的一致性

你可以使用is和as操作符来检查是否遵循某一协议或强制转化为某一类型。

  • is操作符用来检查实例是否遵循了某个协议。
  • as?返回一个可选值,当实例遵循协议时,返回该协议类型;否则返回nil。
  • as用以强制向下转型,如果强转失败,会引起运行时错误。

实例

下面的例子定义了一个 HasArea 的协议,要求有一个Double类型可读的 area:

protocol HasArea {
    var area: Double { get }
}

// 定义了Circle类,都遵循了HasArea协议
class Circle: HasArea {
    let pi = 3.1415927
    var radius: Double
    var area: Double { return pi * radius * radius }
    init(radius: Double) { self.radius = radius }
}

// 定义了Country类,都遵循了HasArea协议
class Country: HasArea {
    var area: Double
    init(area: Double) { self.area = area }
}

// Animal是一个没有实现HasArea协议的类
class Animal {
    var legs: Int
    init(legs: Int) { self.legs = legs }
}

let objects: [AnyObject] = [
    Circle(radius: 2.0),
    Country(area: 243_610),
    Animal(legs: 4)
]

for object in objects {
    // 对迭代出的每一个元素进行检查,看它是否遵循了HasArea协议
    if let objectWithArea = object as? HasArea {
        print("面积为 \(objectWithArea.area)")
    } else {
        print("没有面积")
    }
}

以上程序执行输出结果为:

面积为 12.5663708
面积为 243610.0
没有面积
2017-11-07 09:16:00 weixin_34234823 阅读数 3

数组是一个最常用的数据类型的应用程序。使用数组来组织你的应用程序的数据。具体地说,您可以使用数组类型来控制单个的元素类型,数组的元素类型。一个数组可以存储任何类型的元素从整数字符串类。迅速方便地创建数组在代码中使用一个数组文字:仅仅围绕方括号的逗号分隔的值列表。没有任何其他信息,迅速创建一个数组,包括指定的值,自动推断数组的元素类型。例如:

// An array of 'Int' elements
let oddNumbers = [1, 3, 5, 7, 9, 11, 13, 15]

// An array of 'String' elements
let streets = ["Albemarle", "Brandywine", "Chesapeake"]

您可以创建一个空数组通过指定数组的元素类型的声明。例如:

// Shortened forms are preferred
var emptyDoubles: [Double] = []

// The full type name is also allowed
var emptyFloats: Array<Float> = Array()

如果你需要一个数组与固定数量的preinitialized默认值,使用数组(重复计数:)初始值设定项。

var digitCounts = Array(repeating: 0, count: 10)
print(digitCounts)
// Prints "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"

当您需要执行一个操作数组的所有元素,使用一个工党循环遍历该数组的内容。

for street in streets {
    print("I don't live on \(street).")
}

使用isEmpty属性快速检查是否有任何元素的数组,或者使用count属性找到数组中元素的个数。

if oddNumbers.isEmpty {
    print("I don't know any odd numbers.")
} else {
    print("I know \(oddNumbers.count) odd numbers.")
}

[Swift]协议

阅读数 9582

Swift 协议

阅读数 323

swift协议

阅读数 335

Swift 协议

阅读数 23

Swift之协议

阅读数 1841

没有更多推荐了,返回首页