我们可以像下面的代码那样在类之间进行通信,而不是使用委托/协议模式和通知。我还没有看到像这样的代码示例。但只是好奇地知道为什么这应该起作用。
class Class1 {
var class2Obj: Class2 = Class2()
init() {
class2Obj.class1Obj = self
}
func class1Method() {
print("Parent")
}
}
class Class2 {
weak var class1Obj: Class1?
func class2Method() {
class1Obj.class1Method()
}
}
答案 0 :(得分:3)
你在这里是委托模式。您的委托属性仅称为class1Obj
,而不是更常见的delegate
名称。这里的关键问题是你没有使用协议,因此这两个类是“紧密耦合的”,即Class2
高度依赖于Class1
实现的细节。此外,通过这两个紧密耦合的类,不能立即明确Class1
Class2
可能需要哪些方法。它使Class1
的维护更加困难,因为很容易意外地做出改变以打破Class2
中的行为。它还使Class2
与Class1
以外的其他类一起使用变得困难。
相反,您通常会声明一个协议,以准确地阐明Class2
与可能需要使用它的其他对象之间的契约性质。结果是类没有紧密耦合,即Class2
除了与所讨论的协议的一致性之外,不需要知道另一个类。此外,在编辑Class1
时,如果声明它符合协议,编译器会在您未能实现某些必需的方法或属性时发出警告。
因此,通过预先可忽略不计的工作量,协议使代码更易于维护。它还提供了一些额外的灵活性,您可以将Class2
与Class1
以外的其他内容结合使用。
最重要的是,协议可以使代码更容易维护,更灵活,没有隐藏的假设。
如果您不想使用委托协议模式,另一种方法是使用闭包,其中Class1
提供Class2
可以调用的代码块。所以你可以这样做:
class Class1 {
var class2Obj = Class2()
init() {
class2Obj.handler = { [weak self] in // note `weak` reference which avoids strong reference cycle
self?.class1Method()
}
}
func class1Method() {
print("Parent")
}
}
class Class2 {
var handler: (() -> Void)?
func class2Method() {
handler?()
}
}
虽然委托协议模式在两个类之间有一个丰富的接口时非常有用,但是当两个类之间有一个非常简单的接口时,这个闭包模式。
坦率地说,上述更常见的排列是闭包与Class1
在Class2
中发起的某些特定请求更直接相关。因此,您可以将参数设置为Class2
中相应方法的闭包。此外,您经常会传回数据,所以想象一下我们传回一个可选的String
:
class Class1 {
var class2Obj = Class2()
func performClass2Method() {
class2Obj.class2Method { string in
guard let string = string else { return }
self.class1Method()
}
}
func class1Method() {
print("Parent")
}
}
class Class2 {
func class2Method(completionHandler: @escaping (String?) -> Void) {
// do something which creates `string`
// when done, call the closure, passing that `string` value back
completionHandler(string)
}
}
这些闭包模式是在对象之间进行简单接口的一种很好的方法,但也保持两个类非常松散耦合(即Class2
与Class1
没有依赖关系),就像在...中使用协议一样委托模式做了。但希望上面的闭包示例说明了丰富的委托协议模式的简单替代方法。