Swift 上的协议和组成
Protocols and composition on Swift
我正在尝试了解有关协议的更多信息,但在不了解以下代码段的情况下卡住了。主要是求一些光明和方向,基本都是好的文章和片断的解释。
在 Apple 图书馆协议的一个示例中,它所做的不仅仅是确保 classes 符合它。
他们允许一个 class 中的对象访问其他 class 中的方法,而无需使用传统的 class 继承定义。
Dice class 上的这行代码 let generator: RandomNumberGenerator
允许类型 Dice
的 var d6
访问函数 func random() -> Double
在 Dice
范围外和 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
类型时,它允许封装(抽象),因此只有那部分您可以看到您的实现。
以我的拙见,如果常量 generator
在 Dice
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'
并且您可以将 属性 隐藏在其范围之外。仅供参考。
希望对您有所帮助。
我正在尝试了解有关协议的更多信息,但在不了解以下代码段的情况下卡住了。主要是求一些光明和方向,基本都是好的文章和片断的解释。
在 Apple 图书馆协议的一个示例中,它所做的不仅仅是确保 classes 符合它。
他们允许一个 class 中的对象访问其他 class 中的方法,而无需使用传统的 class 继承定义。
Dice class 上的这行代码 let generator: RandomNumberGenerator
允许类型 Dice
的 var d6
访问函数 func random() -> Double
在 Dice
范围外和 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
类型时,它允许封装(抽象),因此只有那部分您可以看到您的实现。
以我的拙见,如果常量 generator
在 Dice
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'
并且您可以将 属性 隐藏在其范围之外。仅供参考。
希望对您有所帮助。