Objective-C Runtime guide 二(消息转发机制)

Message Forwarding

 

Sending a message toan object that does not handle that message is an error. However, beforeannouncing   the error, the runtimesystem gives the receiving object a second chance to handle the message.

一个类没有某个方法(消息)的实现,如果给这个类发送了这个消息,就会有一个错误。但是,在程序报错之前,运行时机制提供了处理这个消息的第二次机会。

Forwarding转发

If you send amessage to an object that does not handle that message, before announcing anerror the runtime sends the object aforwardInvocation: messagewith an NSInvocation object asits sole argument—the NSInvocation objectencapsulates the original message and the arguments that were passed with it.

当你给一个对象发送了一条他不能处理的消息时,在报错之前,运行时系统会给这个对象发送一个forwardInvocation:消息:这个消息有一个唯一的参数NSInvocation(这个对象包含了原始的消息和参数)

      You can implement a forwardInvocation: method to give a default response tothe message, or to avoid the error in some other way. As its name implies,forwardInvocation: is commonly used to forward the messageto another object.

你可以实现一个forwardInvocation:方法 给这个消息设定一个默认的回复,或者通过其他的方法来避免这个错误。就像他的名字表明的的那样,forwardInvocation:个方法一般用来将这个消息转发给其他的对象
To see the scope and intent of forwarding, imagine the following scenarios:Suppose, first, that you’re designing an object that can respond to a messagecallednegotiate, and you want its response to include the  response of another kind of object. You couldaccomplish this easily by passing anegotiate messageto the other object somewhere in the body of thenegotiatemethod you implement.

想了解转发的范围和目的,想象一下下面的场景,你设计了一个可以响应negotiate方法的对象。然后你想让这个方法的返回值包含另一种对象的返回值。你可以通过把这个negotiate消息转发给另一个你希望实现negotiate方法的的类的。


Take this a step further, and suppose that you want your object’s response to anegotiatemessage to be exactly the response implemented in another class.One way to accomplish this would be to make your class  inherit  the method from the other class. However, itmight not be possible to arrange things this way. There may be good  reasons why your class and the class thatimplements negotiateare in different branches of the inheritance hierarchy.

更进一步讲,   如果你像想让negotiate消息在别的对象中实现更加的准确。一种方法是可以成为这个类的子类,这样子就可以继承这个类的方法了。然而,有时候这种方式是不可行的,比如他们在不同的继承关系分支中。

Even if your classcan’t inherit the negotiate method, you canstill “borrow” it by implementinga version of the methodthat simply  passes the message on to aninstance of the other class:

即使你不可以从继承关系中获得这个方法,你依然可以借来这个方法通过调用其他实现了这个方法的对象。

 

 

This way of doingthings could get a little cumbersome, especially if there were a number ofmessages you wanted your object to pass on to the other object. You’d have toimplement one method to cover each method you wanted to borrow  from the other class. Moreover, it would beimpossible to handle cases where you didn’t know, at the time you wrote thecode, the full set of messages you might want to forward. That set might dependon events at runtime, and it might change as new methods and classes areimplemented in the future.

这样做可能会变得累赘,特便是当你想要给其他的对象转发好多消息的时候。你不得不实现一个方法去包含每一个你想要从别的对象中借来的方法。更多的时候在你编写代码的时候你不可能处理好每个你想要转发的消息。在运行的时候你才能去顶需要转发什么消息,你所要转发的消息时在哪个对象中实现的,或者你要转发的消息都可能会变化。

 

The second chanceoffered by aforwardInvocation:message provides a less adhoc solution to this problem, and one that’s dynamicrather than static. It works like this: When an object can’t respond to a messagebecause it doesn’t have a method matching the selector in the message, the runtimesystem informs the object by sending it a forwardInvocation:message. Every object inherits aforwardInvocation:method from the NSObject class.However, NSObject’s version of the method simply invokesdoesNotRecognizeSelector:. By overriding NSObject’sversion and implementing your own, you can take advantage of the opportunitythat theforwardInvocation: message provides to forward messages toother objects.

 

通过forwardInvocation:这个消息为我们提供了另一种解决这个特殊问题的方式。这个是动态决定的而不是态的。他的工作流程是这样子的:当一个对象因为他的方法不能够匹配消息中的选择器所以不能响应发过来的消息,运行时系统会给对象发送一个forwardInvocation:消息。每一个对象都从NSObject对象继承了这个方法,然而NSObject在这个方法中只是简单的执行了doesNotRecognizeSelector:这个方法。通过重写这个方法(forwardInvocation)你可以利用这个机会把消息转发给其他的对象。

 

To forward amessage, all a forwardInvocation: methodneeds to do is:
Determine where the message should go, and
Send it there with its original arguments.

转发一个消息,(forwardInvocation)方法只需要做这个

决定这个消息需要去哪里

发送时带上他的原始参数:

The message can besent with the invokeWithTarget: method:

 

-(void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([someOtherObject respondsToSelector:
[anInvocation selector]])
[anInvocation invokeWithTarget:someOtherObject];
else
[super forwardInvocation:anInvocation];
}

 

The return value ofthe message that’s forwarded is returned to the original sender. All types ofreturn values can bedeliveredto the sender, including ids, structures, and double-precision floating-point numbers

被转发消息的返回值会被返回给最初的发送者,任何类型的返回值都可以被发送者接受。包括id,和 双精度浮点数。

A forwardInvocation: method can act as a distribution centerfor unrecognized messages, parceling them out to different receivers. Or it canbe a transfer station, sending all messages to the samedestination.It can translate one message into another, or simply “swallow” some messages sothere’s no response and no error. AforwardInvocation: methodcan also consolidate several messages into a single response. WhatforwardInvocation: does is up to the implementor. However,the opportunity it provides for linking objects in a forwarding chain opens uppossibilities for program design.

对于不识别的消息,forwardInvocation: 扮演了一个调度中心的角色。把他们打包发送给不同的接受者。或者他可以作为一个运送站,把所有的消息发送给同一个目的地。他可以把一个消息运送给另一个对象,或者简单的”吞掉”,一些方法,这些方法,没有返回值,也没有错误信息。forwardInvocation:方法还可以巩固几个消息到一个响应。forwardInvocation:方法具体做什么依赖于你的具体实现。而,它提供的机会为连接转发链中的对象提供了程序设计的可能性。

 

Note: The forwardInvocation: method gets to handle messages onlyif they don’t invoke an
existing method in the nominal receiver. If, for example, you want your objectto forward
negotiate messages to another object, it can’t have anegotiate method of its own. If it does, the message will never reachforwardInvocation:

注意只有在调用一个没有被实现的消息时,forwardInvocation:才会被执行,例如如果你想通过这个方法给一个对象发送消息的话,如果这个方法只有在没有被实现的情况下才会被你调用,如果对象实现了这个方法,你是在forwardInvocation方法中是接收不到这个消息的。

For more informationon forwarding and invocations, see the NSInvocationclass specification in the Foundation framework referenc

想了解更多关于invocation的转发信息,请参看NSInvocation 类的参考。

 

 

Forwardingand Multiple Inheritance 转发和多重继承
Forwarding mimics inheritance, and can be used to lend some of theeffects of multiple inheritance to Objective-C programs. As shown inFigure5-1 (page 20), an object that responds to a message by forwarding itappears to borrow or “inherit” a method implementation defined in another class.

转发模拟继承,对于OC程序来说可以用来借用一些多重继承的影响。就像图5-1所示,一个对象通过转发好像是皆有或者继承了在另一个对象中的是实现来实现这个方法。

 

 

In thisillustration, an instance of the Warrior class forwards a negotiate message to an instance of the Diplomat class. The Warrior willappear to negotiate like a Diplomat. It will seem to respond to thenegotiate message, and for all practical purposes it does respond (althoughit’s really a Diplomat that’s doing the work).

在这幅图,一个战士(warrior)类的实例将negotiate(谈判)消息转发到外交官(diploma)类的一个实例。谈判的战士(warrior)将会像一个外交官(diploma)一样出现。响应了negotiate(谈判)信息,,实际上是他(warrior)回应(尽管它真是一个外交官(doploma)的工作)。

 

The object thatforwards a message thus “inherits” methods from two branches of the inheritancehierarchy—its own branch and that of the object that responds to the message.In the example above, it appears as if the Warrior class inherits from Diplomatas well as its own superclass.

转发消息的对象从而继承了两个分支的方法,自己的分支和响应消息的对象。像上面按的例子。(warrior)战士对象,继承了外交官(diplomat)和他他自己的超类。

 

Forwarding providesmost of the features that you typically want from multiple inheritance. However,there’san important difference between the two: Multiple inheritance combinesdifferent capabilities in a singleobject. It tends toward large, multifacetedobjects. Forwarding, on the other hand, assigns separateresponsibilities todisparate objects. It decomposes problems into smaller objects, but associatesthose objects in a way that’s transparent to the message sende

转发提供了大部分通常想从多重继承得到的功能,。然而两者之间,有一件重要的的区别:多重继承单一的对象结合不同的功能。它倾向大,多方面的对象。另一方面,转发, ,向不同的对象分配单独的责任。它可以将问题分解为较小的对象,但那些对象的方式对消息发送者是透明的。

 

 

SurrogateObjects代理对象

Forwarding not onlymimics multiple inheritance, it also makes it possible to develop lightweightobjects that represent or “cover” more substantial objects. The surrogate standsin for the other object andfunnelsmessages to it.

转发不仅仅可以模拟多继承,他还可以开发轻量级的对象代表或者“覆盖”更实质性的对象。代理就是为其他对象提供信息的。

The proxy discussedin “Remote Messaging” in The Objective-C Programming Languageis such a surrogate.A proxy takes care of the administrative details of forwarding messages to aremote receiver, making sure argument values are copied and retrieved acrossthe connection, and so on. But it doesn’t attempt to do much else; it doesn’tduplicate the functionality of the remote object but simply gives the remoteobject a local address, a place where it can receive messages in anotherapplication.
Other kinds of surrogate objects are also possible. Suppose, for example, thatyou have an object that manipulates a lot of data—perhaps it creates acomplicated image or reads the contents of a file on disk. Setting this objectup could be time-consuming, so you prefer to do it lazily—when it’s reallyneeded or when system resources are temporarily idle. At the same time, youneed at least a placeholder for this object in order for the other objects inthe application to function properly.
Inthis circumstance, you could initially create, not the full-fledged object, buta lightweight surrogate for it. This object could do some things on its own,such as answer questions about the data, but mostly it would just hold a placefor the larger object and, when the time came, forward messages to it. When thesurrogate’sforwardInvocation: methodfirst receives a message destined for the other object, it would ensure that theobject existed and would create it if it didn’t. All messages for the larger objectgo through the surrogate, so, as far as the rest of the program is concerned,the surrogate and the larger object would be the same

 

 

Forwardingand Inheritance 转发和继承

Although forwardingmimics inheritance, the NSObjectclassnever confuses the two. Methods like respondsToSelector:and isKindOfClass: look only at the inheritance hierarchy, never at the forwarding chain.If, for example, a Warrior object is asked whether it responds to anegotiate message

尽管转发模拟继承,NSObject类不会混淆这两个概念。方法像respondsToSelector:和isKindOfClass:只看继承层次结构,从不转发链。例如,如果一个战士对象问它是否响应消息进行谈判

 

if ([aWarrior respondsToSelector:@selector(negotiate)] )
...

the answer is NO, even though it can receive negotiate messages without error and respond to them, in a sense, by forwarding them to a Diplomat. (See Figure 5-1 (page 20).)

答案是否定的,尽管它可以接收消息没有错误响应消息,在某种意义上,通过转发他们的外交官。(见图5 - 1(20页)。)

In many cases, NO is the right answer. But it may not be. If you use forwarding toset up a surrogate object or to extend thecapabilities of a class, the forwarding mechanism should probably be astransparent as inheritance. If you want yourobjects to act as if they truly inherited the behavior of the objects theyforward messages to, you’ll need tore-implement the respondsToSelector: and isKindOfClass: methods to include your forwardingalgorithm

在许多情况下,NO 就是正确的答案。但也可能不是。如果你使用转发设置一个代理对象或扩展一个类的功能,转发机制应该继承一样透明。如果你想让你的对象充当他们真正继承他们转发消息的行为对象,您需要重新实现respondsToSelector:isKindOfClass:方法包括你转发算法。

 

-(BOOL)respondsToSelector:(SEL)aSelector
{
if ( [super respondsToSelector:aSelector] )
return YES;
else {
/* Here, test whether the aSelector message can *
* be forwarded to another object and whether that *
* object can respond to it. Return YES if it can. */
}
return NO;
}

 

Inaddition to respondsToSelector: and isKindOfClass: , theinstancesRespondToSelector: method should also mirror theforwarding algorithm. If protocols are used, the conformsToProtocol:method should likewise be added to the list. Similarly, if an objectforwards any remote messages it receives, it should have a version ofmethodSignatureForSelector: that can return accurate descriptions of themethods that ultimately respond to the forwarded messages; for example, ifan object is able to forward a message to its surrogate, you wouldimplement methodSignatureForSelector: as follows:

除了respondsToSelector:isKindOfClass:instancesRespondToSelector:方法
还应该反映转发算法。如果使用协议,conformsToProtocol:方法同样应该被添加到列表中。类似地,如果一个对象将任何远程转发消息接收,它应该有一个版本的methodSignatureForSelector:可以返回准确的描述方法,最终回复转发信息;例如,如果一个物体能够代理转发一条消息,您将实现methodSignatureForSelector:如下:

 

-(NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [surrogate methodSignatureForSelector:selector];
}
return signature;
}

 

You might considerputting the forwarding algorithm somewhere in private code and have all thesemethods, forwardInvocation: included, call it

你可以把这些转发的算法,方法,forwardinvocation:放到你的私有代码中,包含他。调用他。

Note: This is anadvanced technique, suitable only for situations where no other solution ispossible. It is not intended as a replacement for inheritance. If youmust make use of this technique, make sure you fully understand thebehavior of the class doing the forwarding and the class you’re forwardingto

注意:这是一种先进的技术,只适合没有其他解决方案的情况下是可行的。它并不打算取代继承。如果你必须使用这种技术,确保你完全理解类的行为做你转发转发和类

 

The methodsmentioned in this section are described in the NSObjectclass specification in the Foundation framework reference. Forinformation oninvokeWithTarget: , see theNSInvocationclass specification  in theFoundation framework referenc

在这一节中提到的方法描述NSObject类规范的基础框架参考。invokeWithTarget:信息,请参阅NSInvocation类得规范的基础框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值