如何在 Objective C 中调用类方法而不引用类?
我有一系列“策略”对象,我认为将它们作为一组策略类上的类方法来实现很方便。 我为此指定了一个协议,并创建了符合该协议的类(下面仅显示一个),
@protocol Counter
+(NSInteger) countFor: (Model *)model;
@end
@interface CurrentListCounter : NSObject <Counter>
+(NSInteger) countFor: (Model *)model;
@end
然后我有一个符合该协议的类数组(就像 CurrentListCounter 那样)
+(NSArray *) availableCounters {
return [[[NSArray alloc] initWithObjects: [CurrentListCounter class], [AllListsCounter class], nil] autorelease];
}
注意我如何使用对象等类(以及这个可能是我的问题 - 在 Smalltalk 中,类是像其他所有对象一样的对象 - 我不确定它们是否在 Objective-C 中?)
我确切的问题是,当我从策略对象中取出一个策略对象时,我想调用该方法array:
id<Counter> counter = [[MyModel availableCounters] objectAtIndex: self.index];
return [counter countFor: self];
我在 return 语句上收到警告 - 它说 -countFor:在协议中找不到(因此假设它是一个我想调用类方法的实例方法)。 然而,由于我的数组中的对象是类的实例,它们现在就像实例方法(或者从概念上讲它们应该是)。
有没有一种神奇的方法来调用类方法? 或者这只是一个坏主意,我应该只创建策略对象的实例(而不是使用类方法)?
I have a series of "policy" objects which I thought would be convenient to implement as class methods on a set of policy classes. I have specified a protocol for this, and created classes to conform to (just one shown below)
@protocol Counter
+(NSInteger) countFor: (Model *)model;
@end
@interface CurrentListCounter : NSObject <Counter>
+(NSInteger) countFor: (Model *)model;
@end
I then have an array of the classes that conform to this protocol (like CurrentListCounter does)
+(NSArray *) availableCounters {
return [[[NSArray alloc] initWithObjects: [CurrentListCounter class], [AllListsCounter class], nil] autorelease];
}
Notice how I am using the classes like objects (and this might be my problem - in Smalltalk classes are objects like everything else - I'm not sure if they are in Objective-C?)
My exact problem is when I want to call the method when I take one of the policy objects out of the array:
id<Counter> counter = [[MyModel availableCounters] objectAtIndex: self.index];
return [counter countFor: self];
I get a warning on the return statement - it says -countFor: not found in protocol (so its assuming its an instance method where I want to call a class method). However as the objects in my array are instances of class, they are now like instance methods (or conceptually they should be).
Is there a magic way to call class methods? Or is this just a bad idea and I should just create instances of my policy objects (and not use class methods)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Objective-C 中的类确实像实例一样工作——主要的根本区别是保留计数对它们没有任何作用。 但是,您在 -availableCounters 数组中存储的不是实例(
id
类型),而是类,其类型为Class
。 因此,使用上面指定的 -availableCounters 定义,您需要的是:但是,如果您使用实例而不是类,那么在语义上可能会更好。 在这种情况下,您可以执行如下操作:
然后您的模型类可以实现以下内容:
然后您对其的使用将与您上面指定的完全相同:
A class in Objective-C does work like an instance -- the main underlying difference is that retain counting does nothing on them. However, what you're storing in the -availableCounters array aren't instances (the
id
type) but classes, which have a type ofClass
. Therefore, with the -availableCounters definition you specified above, what you need is this:However, it would probably be semantically better if you used instances rather than classes. In that case, you could do something like the following:
Then your model class could implement the following:
Then your use of that would be exactly as you specified above:
这
应该是
首先您有一个符合
的实例。 在第二个中,您有一个符合
的类。 编译器警告是正确的,因为符合
的实例不会响应countFor:
,只有类会响应。This
Should be
In the first you have an instance that conforms to
<Counter>
. In the second you have a class that conforms to<Counter>
. The compiler warning is correct because instances that conform to<Counter>
don't respond tocountFor:
, only classes do.事实证明它确实有效并且警告是不正确的。
所以问题仍然是这是否合理(如果不需要任何状态,则使用类方法)?
以及如何最好地处理警告(我喜欢运行无警告)?
我唯一的解决方法是使用第二个协议(本质上与第一个协议相同,但在实例端声明它):
并且在我访问计数器的地方使用它(以欺骗编译器):
它有点尴尬,但确实有效。 对其他人的观点感兴趣吗?
It turns out it is actually working and the warning is incorrect.
So the question still stands as to whether its a reasonable thing to do (use class methods if they don't need any state)?
And how to best handle the warning (I like to run warning free)?
My only workaround was to have a second protocol (essentially the same as the first but declare it on the instance side):
And where I access the counters use it instead (to trick the compiler):
Its a bit awkward but does work. Am interested in views from others?