gpt4 book ai didi

swift - 为什么闭包不能关闭实例成员

转载 作者:行者123 更新时间:2023-11-30 10:05:55 24 4
gpt4 key购买 nike

我真的很喜欢 Sulthan 的回答(在 Anonymous class in swift 中)它描述了构建一个符合协议(protocol)但其类隐藏在闭包内的对象。这对于构建单例非常有用,并且不会被 Recorder1、Recorder2 等类污染 namespace ......

但是,当我尝试用它做任何有用的事情时,我失败了,因为闭包不会关闭内部类中外部类的实例成员。

protocol EventListener {
func handleEvent(event: Int) -> ()
}

class Recorder {
static var events = [Int]() // static is forced
var listener: EventListener = {
class R : EventListener {
func handleEvent(event: Int) {
events.append(event)
print("Recorded: \(event)")
}
}//
return R()
}()
}// Recorder

class Distributor {
var listeners = [EventListener]()
func register(listener: EventListener){
listeners.append(listener)
}
func distribute(event: Int){
for listener in listeners {
listener.handleEvent(event)
}
}
}

var d = Distributor()
var r1 = Recorder()
var r2 = Recorder()

d.register(r1.listener)
d.register(r2.listener)
d.distribute(10)

print(Recorder.events) // [10, 10] Same event recorded twice.

上面的代码编译并运行。但我希望 Recorder 中的 events 成为实例成员,以便每个 Recorder 都有自己的记录。删除 static 会引发编译器错误:无法使用实例成员“事件”

我尝试在 Recorder 中定义一个实例 func record(event)handleEvent(event) 调用,但出现了相同的错误。

Marius 的回答(在 Instance member cannot be used on type | Closures 中)建议您在定义属性时无法访问实例成员,因此我稍后也尝试像这样计算监听器。

class Recorder { 
var events = [Int]()
var listener: EventListener {
class R : EventListener {
func handleEvent(event: Int) {
events.append(event) // error: can't access events
print("Recorded: \(event)")
}
}
return R()
}
}// Recorder

但是编译器说它无法访问外部自身

如果闭包无法访问外部 self ,那么它们看起来就非常无能为力。在 Java 中,您可以使用诸如 Recorder.self.events 之类的东西来获取外部 self。并且 Recorder.self. 可能仅在存在名称冲突时才需要(?)

Swift 是这样设计的还是我错过了什么?

你会如何编写它,以便RecorderDistributor提供一个除了接收handleEvent消息之外什么都不做的对象?

非常感谢。

最佳答案

我不相信有办法在部分初始化的记录器中关闭事件。但是,您可以为记录器创建一个两阶段的初始化过程。第一阶段使用默认的空监听器创建 Recorder 对象。第二阶段创建一个适当的事件闭包并将其分配给监听器。

此实现没有 EventListener 协议(protocol)。我确信有一种简单的方法可以做到这一点,但对于嵌套类来说,这似乎有点矫枉过正。因此,Distributor 不是包含对象数组,而是包含闭包。我们让 Distributor 直接包含闭包数组。

除了对 initialize 的额外调用之外,您的 API 不会更改。

typealias EventListener = (Int) -> ()

class Distributor {
var listeners = [EventListener]()
func register(listener: EventListener){
listeners.append(listener)
}
func distribute(event: Int){
for listener in listeners {
listener(event)
}
}
}

class Recorder {
var events = [Int]()
var listener: EventListener = {
(event: Int) in
fatalError("Listener not initialized")
}
func initialize() {
listener = {
(event: Int) in
self.events.append(event)
print("Recorded: \(event)")
}
}
}

var d = Distributor()

// 1st stage of Recorder instantiation
var r1 = Recorder()
var r2 = Recorder()

// 2nd stage
// r1.listener can now have a closure that includes an init'ed events
r1.initialize()
r2.initialize()

d.register(r1.listener)
d.register(r2.listener)
d.distribute(10)

print(r1.events)
print(r2.events)

关于swift - 为什么闭包不能关闭实例成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35970401/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com