我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?
如果不是,在Objective-C中,我能有多接近抽象类?
我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?
如果不是,在Objective-C中,我能有多接近抽象类?
当前回答
不,在Objective-C中无法创建抽象类。
你可以模拟一个抽象类——通过让methods/ selectors调用doesNotRecognizeSelector:从而引发一个异常,使该类不可用。
例如:
- (id)someMethod:(SomeObject*)blah
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
你也可以为init这样做。
其他回答
你不能创建一个委托吗?
委托就像一个抽象基类,你说需要定义什么函数,但实际上你不定义它们。
然后,每当你实现委托(即抽象类)时,编译器就会警告你需要为哪些可选函数和强制函数定义行为。
对我来说,这听起来像一个抽象基类。
我想出的解决办法是:
为“抽象”类中需要的所有内容创建一个协议 创建一个实现协议的基类(也可以称之为抽象类)。对于所有你想要“抽象”的方法,在.m文件中实现它们,而不是在.h文件中实现。 让你的子类继承基类并实现协议。
这样,编译器就会对协议中没有由你的子类实现的任何方法发出警告。
它不像Java中那样简洁,但您确实会得到所需的编译器警告。
只是重复了上面@Barry Wark的回答(并更新到iOS 4.3),并把这个留给我自己参考:
#define mustOverride() @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]
#define methodNotImplemented() mustOverride()
在你的方法中你可以使用这个
- (void) someMethod {
mustOverride(); // or methodNotImplemented(), same thing
}
注意:不确定是否使宏看起来像一个C函数是一个好主意,但我会保持它直到学校相反。我认为使用NSInvalidArgumentException(而不是NSInternalInconsistencyException)更正确,因为这是运行时系统在响应doesNotRecognizeSelector被调用时抛出的(参见NSObject文档)。
我通常只在我想要抽象的类中禁用init方法:
- (instancetype)__unavailable init; // This is an abstract class.
这将在编译时在该类上调用init时生成一个错误。然后我用类方法来处理其他事情。
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
您也可以使用协议和其他解决方案-但这是最简单的解决方案之一。