Swift 上的协议和组成

Protocols and composition on Swift

我正在尝试了解有关协议的更多信息,但在不了解以下代码段的情况下卡住了。主要是求一些光明和方向,基本都是好的文章和片断的解释。

在 Apple 图书馆协议的一个示例中,它所做的不仅仅是确保 classes 符合它。

他们允许一个 class 中的对象访问其他 class 中的方法,而无需使用传统的 class 继承定义。

Dice class 上的这行代码 let generator: RandomNumberGenerator 允许类型 Dicevar d6 访问函数 func random() -> DoubleDice 范围外和 LinearCongruentialGenerator 范围内,并使用 RandomNumberGenerator 来建立这座桥。

还允许在 .ramdom() 再次不在 Dices 范围内时执行以下调用 d6.generator.random()

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
    }
}

class Dice {
    let sides: Int
    let generator: RandomNumberGenerator

    init(sides: Int, generator: RandomNumberGenerator) {

        println(generator.random())

        self.sides = sides
        self.generator = generator
    }

    func roll() -> Int {
        return Int(generator.random() * Double(sides)) + 1
    }
}

var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())

更新问题

感谢您的回答!通过做一些研究,我想我刚刚接触了构图。所以我写了下面的代码来更好地举例说明组合,而不使用协议或委托。只是纯粹的组成。如果我做对了,请告诉我,因为它可能会帮助其他试图理解构图的人。

class A {

    var a1: String

    init (valueToA: String){
        self.a1 = valueToA
    }

    func aFunc1() -> A {
        return self
    }
}


class B {

    var b1: A

    init (valueToB: A ) {
        self.b1 = valueToB
    }

    func bFunc1(){
        println("I am bFunc and I am calling aFunc \(b1.aFunc1())")
    }

}

var myA = A(valueToA: "Initiated myA with this string")
//myA.aFunc1()

var myB = B(valueToB: myA)
myB.b1 = A(valueToA: "a value to B")
myB.b1.aFunc1()

The same code but now with protocols

protocol myProtocol {
    func protocolFunc(value: String) -> String
}

class A: myProtocol {

    var a1: String

    init (valueToA: String){
        self.a1 = valueToA
    }

    func aFunc1() -> A {
        return self
    }

    func protocolFunc(value: String) -> String {
        return value
    }

}

class B {

    var b1: A
    var b2: myProtocol

    init (valueToB1: A, valueToB2: myProtocol ) {
        self.b1 = valueToB1
        self.b2 = valueToB2
    }

    func bFunc1(){
        println("I am bFunc and I am calling aFunc \(b1.aFunc1())")
    }

    func callProtocolFuncOnA (value: String) {
        b1.protocolFunc(value)
    }

}

var myA1 = A(valueToA: "my A 1 created")
var myA2 = A(valueToA: "my A 2 created")


var myB = B(valueToB1: myA1, valueToB2: A(valueToA: "my A 3 created"))

myB.callProtocolFuncOnA("calling other function")

正如@DevAndArtist 在他的评论中所说,当在 Dice class 的初始化程序中传递 RandomNumberGenerator 类型时,它允许封装(抽象),因此只有那部分您可以看到您的实现。

以我的拙见,如果常量 generatorDice class 范围之外不可见,如您在问题中所说,例如使他的访问修饰符private,但请记住,在您的示例中,所有内容都设置在同一个 swift 文件中,这意味着 private 访问修饰符不同于其他编程语言,如 C#、Java,等等

即使执行 private 你也可以在你的调用中访问 d6.generator.random() 因为它存在于同一个 Swift 文件中,如果你可以隐藏 属性 的唯一方法为 Dice class 创建一个新的 Swift 文件,然后当 属性 是私有的时调用这个当然:

var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
println(d6.generator.random())

给你以下错误:

'Dice' does not have a member named 'generator'

并且您可以将 属性 隐藏在其范围之外。仅供参考。

希望对您有所帮助。