2016-03-13 39 views
0

我真的很喜欢Sulthan的回答(在Anonymous class in swift) 它描述了建立一个符合协议,但其类隐藏在闭包中的对象。这将是很好的建设单身人士,并没有污染的名称空间与类像Recorder1,Recorder2 ...为什么不能关闭实例成员

然而,当我尝试做任何有用的事情,我失败了,因为封闭不会关闭外类内部类的实例成员。

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成为一个实例成员,以便每个记录器都有自己的记录。删除static会抛出编译器错误:实例成员'events'不能使用

我试着在Recorder中为handleEvent(event)定义一个实例func record(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 

但是编译器说,它无法访问的外自我

如果他们无法访问外部自我,闭包看起来很无能。在Java中,你可以使用类似Recorder.self.events的东西来获得外部自我。而Recorder.self.可能只有当有名称冲突时才需要(?)

斯威夫特是这样设计的还是我错过了什么?

你会如何编写它,所以RecorderDistributor一个对象,除了接收handleEvent消息什么都不能做?

非常感谢。

回答

1

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

该实现没有EventListener协议。我相信有一个简单的方法可以做到这一点,但对于嵌套类似乎是矫枉过正。因此,而不是包含包含闭包的对象数组的分发服务器。我们正在让分销商直接包含关闭数组。

除了额外致电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) 
+0

谢谢你看这个!让我熬一会儿吧。 – adazacom

0

使用价格Ringo的2阶段初始化,并具有录音机通self到内部类,我已经得到了类隐藏我一直在寻找。它比我希望的稍微冗长一点,但它具有使记录器实例成员的生命周期清晰的优点。例如,它避免了events周围的复制vs参考混淆。 self也可以很容易地通过其他方式传递数据:adjustment

价格Ringo的解决方案更加优雅,适合这一特定问题。此解决方案更为通用,可与任何现有协议配合使用。一般来说,我试图将面向协议的模式整合到我的代码中。此解决方案创建的对象除符合它们的协议外没有其他类型。

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

class Recorder { 
    var events = [Int]() // example of data out 
    let adjustment: Int // example of data in 
    var listener: EventListener = { 
     class __: EventListener { 
      func handleEvent(event: Int) { } 
     } 
     return __() 
    }() 
    init(adjustment: Int){ 
     self.adjustment = adjustment 
     initializeListener() 
    } 
    private func initializeListener() { 
     listener = { 
      class __: EventListener { 
       unowned var recorder: Recorder 
       init(recorder: Recorder){ 
        self.recorder = recorder 
       } 
       func handleEvent(event: Int) { 
        let adjustedEvent = 
          recorder.adjustment * event 
        recorder.events.append(adjustedEvent) 
       // print("Recorded: \(adjustedEvent)") 
       } 
      } 
      return __(recorder: self) 
     }() 
    } 
}// Recorder 

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

var d = Distributor() 
var r1 = Recorder(adjustment: 2) 
var r2 = Recorder(adjustment: 3) 

d.addListener(r1.listener) 
d.addListener(r2.listener) 
d.distributeEvent(10) 

print(r1.events) // [20] 
print(r2.events) // [30] 

如果您还在阅读,我有一个问题。我已经使实例成员__>recorder无主,以避免保留。我还需要使Recorder>listener无主吗?

相关问题