Objective-C 中的动态方法创建
在The Pragmatic Programmer一书中,作者建议所有方法输入都应该经过验证。这样可以尽早发现方法中的问题并轻松追踪其来源。
在我的 Mac 应用程序中,我通过创建一个 Assert
类来完成此任务。这个类有几个类方法。这些方法确定是否满足某些先决条件,如果不满足,则抛出异常。典型的断言可能看起来像这样:
-(void) setWidth: (int) theWidth {
[Assert integer: width isGreaterThanInteger: 0];
width = theWidth;
}
这非常有效,并且显着减少了我花在寻找错误上的时间。然而,我最近注意到一些断言方法作为谓词非常有用。例如,我的 integer:isGreaterThanInteger:andLessThanInteger:
和我的 stringIsNotEmpty:
方法同样有用。为此,我创建了第二个类 Predicate
,其中填充了几个更有用的谓词方法。因此,我从断言方法中取出逻辑,并将其移至 Predicate
中,然后重写我的 Assert
方法,如下所示:
if ![Predicate predicateMethod]
throw exception
这已变成维护噩梦。如果我在 Predicate
中更改方法名称,我还必须在 Assert
中更改它以保持一致。如果我更新 Assert
方法的文档,那么我必须对 Predicate
方法执行相同的操作。
理想情况下,我希望重建 Assert 类,以便在对其调用任何方法时,它会拦截选择器。然后可以检查 Predicate 类以查看它是否响应选择器,如果响应,则使用传递到 Predicate 的相同参数在 Predicate 上调用该方法。 断言
方法。如果 Predicate
方法返回 false,则会引发异常。
Objective-C 有没有办法做到这一点?
谢谢。
In the book The Pragmatic Programmer, the authors suggest that all method inputs should be validated. This allows problems with a method to be caught early and their sources traced easily.
In my Mac application, I accomplished this by creating an Assert
class. This class has several class methods. These methods determine if some precondition is met, and if it is not, then an exception is thrown. A typical assertion might looks something like this:
-(void) setWidth: (int) theWidth {
[Assert integer: width isGreaterThanInteger: 0];
width = theWidth;
}
This works really well, and significantly reduced the amount of time I've spend bug hunting. However, I've noticed lately some of the assertion methods are very useful as predicates. For example, my integer:isGreaterThanInteger:andLessThanInteger:
and my stringIsNotEmpty:
methods are equally useful. To this end, I created a second class Predicate
, which I filled with several of my more useful predicate methods. So I took the logic from the assert methods, and moved it into Predicate
, and then rewrote my Assert
methods like the following:
if ![Predicate predicateMethod]
throw exception
This has turned into a maintenance nightmare. If I change the name of a method name in Predicate
, I must also change it in Assert
to stay consistent. If I update the documentation of an Assert
method, then I must do the same to a Predicate
method.
Ideally, I would like the reconstruct the Assert
class so that when any method is called on it, it intercepts the selector. The Predicate
class can then be checked to see if it responds to the selector, and if it does, the method is called on Predicate
with the same arguments that were passed into the Assert
method. If the Predicate
method returns false, then an exception is thrown.
Is there a way to do this in Objective-C?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用
-forwardingTargetForSelector:
简单地将方法转发给另一个方法对象,但如果您想要高级行为(例如检查返回值以查看其是否为 false),您可能需要使用-forwardInspiration:
。 (但是,请注意,文档说这比前一种选择“昂贵得多”。)You could use
-forwardingTargetForSelector:
to simply forward the method to another object, but if you want advanced behavior (like checking the return value to see if it's false), you may need to use-forwardInvocation:
. (However, note that the documentation says this is "much more expensive" than the former option.)如果您使用纯 Objective-C,您应该在此处查看“转发”讨论。它基本上描述了如何准确地执行您想要的操作,包括示例代码。
如果您使用 Cocoa,那么您可能必须使用 forwardInitation: 代替。
If you're using pure Objective-C, you should see the "Forwarding" discussion here. It basically describes how to do exactly what you want, including example code.
If you're using Cocoa then you might have to use forwardInvocation: instead.
我最终覆盖了
resolveClassMethod:
。虽然覆盖forwardInspiration
可能有效(我必须找出某种方法来为类对象覆盖它),但resolveClassMethod:
似乎是更简单、更有效的方法。这是我的最终实现的样子:我唯一无法真正弄清楚的是如何从方法签名中获取类型编码。它似乎没有影响方法的输出,但如果可以的话我想修复它。
I ended up overriding
resolveClassMethod:
. While overridingforwardInvocation
might have worked (I would have had to figure out some way to override it for the class object),resolveClassMethod:
seems like it's the easier and more efficient method. Here's what my final implementation ended up looking like:The only thing I couldn't really figure out was how to get the type encoding from the method signature. It didn't seem to affect the output of the methods, but I would like to fix it if I can.