我最初是一名Java程序员,现在使用Objective-C。我想创建一个抽象类,但这在Objective-C中似乎不可能。这可能吗?

如果不是,在Objective-C中,我能有多接近抽象类?


当前回答

创建抽象类的简单示例

// Declare a protocol
@protocol AbcProtocol <NSObject>

-(void)fnOne;
-(void)fnTwo;

@optional

-(void)fnThree;

@end

// Abstract class
@interface AbstractAbc : NSObject<AbcProtocol>

@end

@implementation AbstractAbc

-(id)init{
    self = [super init];
    if (self) {
    }
    return self;
}

-(void)fnOne{
// Code
}

-(void)fnTwo{
// Code
}

@end

// Implementation class
@interface ImpAbc : AbstractAbc

@end

@implementation ImpAbc

-(id)init{
    self = [super init];
    if (self) {
    }
    return self;
}

// You may override it    
-(void)fnOne{
// Code
}
// You may override it
-(void)fnTwo{
// Code
}

-(void)fnThree{
// Code
}

@end

其他回答

问题的答案散落在已经给出答案的评论中。所以,我只是在这里总结和简化。

Option1:协议

如果你想创建一个没有实现的抽象类,请使用“协议”。继承协议的类必须实现协议中的方法。

@protocol ProtocolName
// list of methods and properties
@end

选项2:模板方法模式

如果你想创建一个带有部分实现的抽象类,如“Template Method Pattern”,那么这就是解决方案。 Objective-C -模板方法模式?

Cocoa不提供任何所谓抽象的东西。我们可以创建一个只在运行时检查的类抽象,而在编译时不检查。

事实上,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

只是重复了上面@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文档)。

使用@property和@dynamic也可以。如果您声明了一个动态属性,但没有给出匹配的方法实现,那么所有内容仍然会在没有警告的情况下编译,并且如果您试图访问它,将在运行时得到一个无法识别的选择器错误。这本质上与调用[self doesNotRecognizeSelector:_cmd]是一样的,但是输入要少得多。