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

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


当前回答

也许这种情况只会发生在开发阶段,所以这是可行的:

- (id)myMethodWithVar:(id)var {
   NSAssert(NO, @"You most override myMethodWithVar:");
   return nil;
}

其他回答

另一种替代方法

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

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

这消除了重写init的必要性

(更多相关的建议)

我想有一种方法让程序员知道“不要从子调用”,并完全覆盖(在我的情况下,仍然提供了一些默认功能,代表父时,未扩展):

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的实现,而不是不得不挖掘注释/文档或…假设。

创建抽象类的简单示例

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

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