我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?
如果不是,在Objective-C中,我能有多接近抽象类?
我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?
如果不是,在Objective-C中,我能有多接近抽象类?
当前回答
问题的答案散落在已经给出答案的评论中。所以,我只是在这里总结和简化。
Option1:协议
如果你想创建一个没有实现的抽象类,请使用“协议”。继承协议的类必须实现协议中的方法。
@protocol ProtocolName
// list of methods and properties
@end
选项2:模板方法模式
如果你想创建一个带有部分实现的抽象类,如“Template Method Pattern”,那么这就是解决方案。 Objective-C -模板方法模式?
其他回答
使用@property和@dynamic也可以。如果您声明了一个动态属性,但没有给出匹配的方法实现,那么所有内容仍然会在没有警告的情况下编译,并且如果您试图访问它,将在运行时得到一个无法识别的选择器错误。这本质上与调用[self doesNotRecognizeSelector:_cmd]是一样的,但是输入要少得多。
Typically, Objective-C class are abstract by convention only—if the author documents a class as abstract, just don't use it without subclassing it. There is no compile-time enforcement that prevents instantiation of an abstract class, however. In fact, there is nothing to stop a user from providing implementations of abstract methods via a category (i.e. at runtime). You can force a user to at least override certain methods by raising an exception in those methods implementation in your abstract class:
[NSException raise:NSInternalInconsistencyException
format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
如果您的方法返回一个值,那么使用起来会更容易一些
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
这样就不需要从方法中添加return语句了。
如果抽象类实际上是一个接口(即没有具体的方法实现),使用Objective-C协议是更合适的选择。
与其尝试创建抽象基类,不如考虑使用协议(类似于Java接口)。这允许您定义一组方法,然后接受符合协议的所有对象并实现这些方法。例如,我可以定义一个操作协议,然后有一个这样的函数:
- (void)performOperation:(id<Operation>)op
{
// do something with operation
}
其中op可以是任何实现Operation协议的对象。
如果您需要抽象基类做的不仅仅是定义方法,那么您可以创建一个常规的Objective-C类并防止它被实例化。只需重写- (id)init函数,并使其返回nil或assert(false)。这不是一个非常干净的解决方案,但由于Objective-C是完全动态的,所以实际上没有与抽象基类直接等价的东西。
Cocoa不提供任何所谓抽象的东西。我们可以创建一个只在运行时检查的类抽象,而在编译时不检查。
不,在Objective-C中无法创建抽象类。
你可以模拟一个抽象类——通过让methods/ selectors调用doesNotRecognizeSelector:从而引发一个异常,使该类不可用。
例如:
- (id)someMethod:(SomeObject*)blah
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
你也可以为init这样做。