我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?
如果不是,在Objective-C中,我能有多接近抽象类?
我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?
如果不是,在Objective-C中,我能有多接近抽象类?
当前回答
你可以使用@Yar提出的方法(做了一些修改):
#define mustOverride() @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]
#define setMustOverride() NSLog(@"%@ - method not implemented", NSStringFromClass([self class])); mustOverride()
在这里你会得到这样的消息:
<Date> ProjectName[7921:1967092] <Class where method not implemented> - method not implemented
<Date> ProjectName[7921:1967092] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[<Base class (if inherited or same if not> <Method name>] must be overridden in a subclass/category'
或断言:
NSAssert(![self respondsToSelector:@selector(<MethodName>)], @"Not implemented");
在这种情况下,你会得到:
<Date> ProjectName[7926:1967491] *** Assertion failure in -[<Class Name> <Method name>], /Users/kirill/Documents/Projects/root/<ProjectName> Services/Classes/ViewControllers/YourClass:53
您也可以使用协议和其他解决方案-但这是最简单的解决方案之一。
其他回答
与其尝试创建抽象基类,不如考虑使用协议(类似于Java接口)。这允许您定义一组方法,然后接受符合协议的所有对象并实现这些方法。例如,我可以定义一个操作协议,然后有一个这样的函数:
- (void)performOperation:(id<Operation>)op
{
// do something with operation
}
其中op可以是任何实现Operation协议的对象。
如果您需要抽象基类做的不仅仅是定义方法,那么您可以创建一个常规的Objective-C类并防止它被实例化。只需重写- (id)init函数,并使其返回nil或assert(false)。这不是一个非常干净的解决方案,但由于Objective-C是完全动态的,所以实际上没有与抽象基类直接等价的东西。
另一种替代方法
只要在抽象类和断言或异常中检查类,无论你喜欢什么。
@implementation Orange
- (instancetype)init
{
self = [super init];
NSAssert([self class] != [Orange class], @"This is an abstract class");
if (self) {
}
return self;
}
@end
这消除了重写init的必要性
你不能创建一个委托吗?
委托就像一个抽象基类,你说需要定义什么函数,但实际上你不定义它们。
然后,每当你实现委托(即抽象类)时,编译器就会警告你需要为哪些可选函数和强制函数定义行为。
对我来说,这听起来像一个抽象基类。
也许这种情况只会发生在开发阶段,所以这是可行的:
- (id)myMethodWithVar:(id)var {
NSAssert(NO, @"You most override myMethodWithVar:");
return nil;
}
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协议是更合适的选择。