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

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


当前回答

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

其他回答

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

我想出的解决办法是:

为“抽象”类中需要的所有内容创建一个协议 创建一个实现协议的基类(也可以称之为抽象类)。对于所有你想要“抽象”的方法,在.m文件中实现它们,而不是在.h文件中实现。 让你的子类继承基类并实现协议。

这样,编译器就会对协议中没有由你的子类实现的任何方法发出警告。

它不像Java中那样简洁,但您确实会得到所需的编译器警告。

创建抽象类的简单示例

// 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

另一种替代方法

只要在抽象类和断言或异常中检查类,无论你喜欢什么。

@implementation Orange
- (instancetype)init
{
    self = [super init];
    NSAssert([self class] != [Orange class], @"This is an abstract class");
    if (self) {
    }
    return self;
}
@end

这消除了重写init的必要性

你可以使用@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

您也可以使用协议和其他解决方案-但这是最简单的解决方案之一。