ruby 中的代表从 Cocoa 开发人员背景中解释
delegates in ruby explained from a Cocoa developer background
我真的希望有人能回答这个问题。我想我绝对不是唯一对此感到困惑的人,我找不到任何可以清楚地解释这个概念的东西。
我对委托模式的理解来源于对Cocoa
框架的研究。对我来说,Cocoa 的实现非常清晰。但是我很难在 Ruby 中理解它(标准库的 Delegator
、SimpleDelegator
与 ActiveSupport
的 Delegate
)。这对我来说没什么意义。主要是因为一个是类型安全的,另一个是鸭子类型。您已经可以看到我的观点,但请允许我展开...这是我对如何在 Cocoa:
中使用委托模式的总结
我们的“成分”是:2 classes、A
和 B
以及一个 protocol
,即 Cocoa 用于预定义用于委派的一组方法。
模式的实现基本如下:
A
定义委托给 B
.
的方法集
B
的委托设置为 A
=> B
现在可以像这样调用委托方法:@delegate.send(a_delegated_method)
我没有把 Ruby 与鸭子类型联系在一起的事实,因此您可以将任何方法调用发送到任何对象,对吗?所以使用我刚才解释的模式,只要这两个对象在同一个域中,你就可以在 A
@b.send(:a_delegated_method)
中说,反之亦然,在 B
@a.send(:another_delegated_method)
中。
难道Ruby中有委托的地方就是定义委托方法的地方?意思是我们从 class A
发送到 属性 @b
(@b(:delegated_method)
) 一个在 A
本身定义的 :delegated_method
?
希望这不会太混乱。我自己很困惑为什么委托甚至存在于鸭子打字语言中,以及 Delegator
、SimpleDelegator
和 ActiveSupport
的 Delegate
.
之间有什么区别
我不清楚您是否了解委派在 Cocoa 中的工作原理。 Cocoa 中委托模式的常见变体确实涉及协议,但这只是让编译器安静下来的一种方式。
所以让我们先谈谈让编译器安静下来。您不能将 woohoo
消息发送到 Objective-C 中的对象,除非以下两个条件之一为真:
编译器有理由相信此对象可能会响应 woohoo
消息。
让编译器暂停判断
如今,通常使用第一种方法 - 这就是协议的用途。但情况并非总是如此。过去,授权主要依赖于 非正式协议 。 Cocoa 中仍然存在非正式协议。这个想法是要么该方法通过类别注入到 NSObject 中,要么您小心地将对象键入 id
以便它可以发送任何消息。
现在让我们谈谈活力。不再使用非正式协议的原因是引入了允许协议声明可选成员的功能。但是活力还是需要的!我们可能会以某种方式满足编译器,但在运行时,我们必须确保将特定消息发送到一定的对象。您的应用委托可能采用 UIApplicationDelegate,但 Cocoa 不会向它发送 applicationDidBecomeActive:
消息,除非您的应用委托 class 实现 applicationDidBecomeActive:
- 如果是这样,你会崩溃,那不是很好。
此外,如果您可以通过编译器,您可以在 Objective-C 中执行比这更动态的委托,如此处解释:
我们的想法是在运行时直接向对象发送消息!如果对象 A 无法处理的消息到达,它可以查看对象 B 是否处理它。如果是,它会将消息传递给对象 B。所以我们可能不会崩溃!我在我的一个应用程序中使用了这种方法:
- (id)forwardingTargetForSelector:(SEL)aSelector {
if ([self.originalDataSource respondsToSelector: aSelector])
return self.originalDataSource;
return [super forwardingTargetForSelector:aSelector];
}
在该代码中,我是说如果消息到达但我无法处理它,我应该尝试将它发送到另一个对象,称为 self.originalDataSource
。
如果您考虑一下,这几乎与 Ruby 授权相同。我有一个辅助对象,我无法处理的消息会传递给它。
此模式的另一个常见用途是包装 Cocoa 集合。你不能 subclass,比如 NSArray,因为它是一个 class 集群,所以正确的方法是包装它。然后,您只需将所有内容转发给 NSArray,很快,您就被鸭子类型化为 NSArray!就您的方法而言,您看起来像一个 NSArray。然后你引入了一些行为上的差异,现在你被鸭子类型化为一个自定义的 NSArray。
我真的希望有人能回答这个问题。我想我绝对不是唯一对此感到困惑的人,我找不到任何可以清楚地解释这个概念的东西。
我对委托模式的理解来源于对Cocoa
框架的研究。对我来说,Cocoa 的实现非常清晰。但是我很难在 Ruby 中理解它(标准库的 Delegator
、SimpleDelegator
与 ActiveSupport
的 Delegate
)。这对我来说没什么意义。主要是因为一个是类型安全的,另一个是鸭子类型。您已经可以看到我的观点,但请允许我展开...这是我对如何在 Cocoa:
我们的“成分”是:2 classes、A
和 B
以及一个 protocol
,即 Cocoa 用于预定义用于委派的一组方法。
模式的实现基本如下:
的方法集A
定义委托给B
.B
的委托设置为A
=>
B
现在可以像这样调用委托方法:@delegate.send(a_delegated_method)
我没有把 Ruby 与鸭子类型联系在一起的事实,因此您可以将任何方法调用发送到任何对象,对吗?所以使用我刚才解释的模式,只要这两个对象在同一个域中,你就可以在 A
@b.send(:a_delegated_method)
中说,反之亦然,在 B
@a.send(:another_delegated_method)
中。
难道Ruby中有委托的地方就是定义委托方法的地方?意思是我们从 class A
发送到 属性 @b
(@b(:delegated_method)
) 一个在 A
本身定义的 :delegated_method
?
希望这不会太混乱。我自己很困惑为什么委托甚至存在于鸭子打字语言中,以及 Delegator
、SimpleDelegator
和 ActiveSupport
的 Delegate
.
我不清楚您是否了解委派在 Cocoa 中的工作原理。 Cocoa 中委托模式的常见变体确实涉及协议,但这只是让编译器安静下来的一种方式。
所以让我们先谈谈让编译器安静下来。您不能将 woohoo
消息发送到 Objective-C 中的对象,除非以下两个条件之一为真:
编译器有理由相信此对象可能会响应
woohoo
消息。让编译器暂停判断
如今,通常使用第一种方法 - 这就是协议的用途。但情况并非总是如此。过去,授权主要依赖于 非正式协议 。 Cocoa 中仍然存在非正式协议。这个想法是要么该方法通过类别注入到 NSObject 中,要么您小心地将对象键入 id
以便它可以发送任何消息。
现在让我们谈谈活力。不再使用非正式协议的原因是引入了允许协议声明可选成员的功能。但是活力还是需要的!我们可能会以某种方式满足编译器,但在运行时,我们必须确保将特定消息发送到一定的对象。您的应用委托可能采用 UIApplicationDelegate,但 Cocoa 不会向它发送 applicationDidBecomeActive:
消息,除非您的应用委托 class 实现 applicationDidBecomeActive:
- 如果是这样,你会崩溃,那不是很好。
此外,如果您可以通过编译器,您可以在 Objective-C 中执行比这更动态的委托,如此处解释:
我们的想法是在运行时直接向对象发送消息!如果对象 A 无法处理的消息到达,它可以查看对象 B 是否处理它。如果是,它会将消息传递给对象 B。所以我们可能不会崩溃!我在我的一个应用程序中使用了这种方法:
- (id)forwardingTargetForSelector:(SEL)aSelector {
if ([self.originalDataSource respondsToSelector: aSelector])
return self.originalDataSource;
return [super forwardingTargetForSelector:aSelector];
}
在该代码中,我是说如果消息到达但我无法处理它,我应该尝试将它发送到另一个对象,称为 self.originalDataSource
。
如果您考虑一下,这几乎与 Ruby 授权相同。我有一个辅助对象,我无法处理的消息会传递给它。
此模式的另一个常见用途是包装 Cocoa 集合。你不能 subclass,比如 NSArray,因为它是一个 class 集群,所以正确的方法是包装它。然后,您只需将所有内容转发给 NSArray,很快,您就被鸭子类型化为 NSArray!就您的方法而言,您看起来像一个 NSArray。然后你引入了一些行为上的差异,现在你被鸭子类型化为一个自定义的 NSArray。