我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?
如果不是,在Objective-C中,我能有多接近抽象类?
我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?
如果不是,在Objective-C中,我能有多接近抽象类?
当前回答
事实上,Objective-C没有抽象类,但是您可以使用协议来达到同样的效果。下面是例子:
CustomProtocol.h
#import <Foundation/Foundation.h>
@protocol CustomProtocol <NSObject>
@required
- (void)methodA;
@optional
- (void)methodB;
@end
TestProtocol.h
#import <Foundation/Foundation.h>
#import "CustomProtocol.h"
@interface TestProtocol : NSObject <CustomProtocol>
@end
TestProtocol.m
#import "TestProtocol.h"
@implementation TestProtocol
- (void)methodA
{
NSLog(@"methodA...");
}
- (void)methodB
{
NSLog(@"methodB...");
}
@end
其他回答
从Omni组邮件列表:
Objective-C没有像Java那样的抽象编译器结构 这一次。
因此,您所要做的就是将抽象类定义为任何其他正常类 并为抽象方法实现方法存根 空或报告不支持选择器。例如……
- (id)someMethod:(SomeObject*)blah
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
我还执行以下操作来防止抽象的初始化 通过默认初始化式初始化。
- (id)init
{
[self doesNotRecognizeSelector:_cmd];
[self release];
return nil;
}
使用@property和@dynamic也可以。如果您声明了一个动态属性,但没有给出匹配的方法实现,那么所有内容仍然会在没有警告的情况下编译,并且如果您试图访问它,将在运行时得到一个无法识别的选择器错误。这本质上与调用[self doesNotRecognizeSelector:_cmd]是一样的,但是输入要少得多。
我通常只在我想要抽象的类中禁用init方法:
- (instancetype)__unavailable init; // This is an abstract class.
这将在编译时在该类上调用init时生成一个错误。然后我用类方法来处理其他事情。
Objective-C没有内置的方法来声明抽象类。
(更多相关的建议)
我想有一种方法让程序员知道“不要从子调用”,并完全覆盖(在我的情况下,仍然提供了一些默认功能,代表父时,未扩展):
typedef void override_void;
typedef id override_id;
@implementation myBaseClass
// some limited default behavior (undesired by subclasses)
- (override_void) doSomething;
- (override_id) makeSomeObject;
// some internally required default behavior
- (void) doesSomethingImportant;
@end
这样做的好处是程序员会看到声明中的“override”,并且知道他们不应该调用[super ..]。
当然,必须为此定义单独的返回类型是很难看的,但它可以作为一个足够好的视觉提示,并且您可以很容易地在子类定义中不使用“overrides”部分。
当然,当扩展是可选的时,类仍然可以有默认实现。但是,就像其他答案所说的那样,在适当的时候实现一个运行时异常,比如对于抽象(虚拟)类。
如果有像这样的内置编译器提示就好了,甚至提示什么时候最好预/后调用super的实现,而不是不得不挖掘注释/文档或…假设。
只是重复了上面@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文档)。