我最初是一名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
其他回答
我想出的解决办法是:
为“抽象”类中需要的所有内容创建一个协议 创建一个实现协议的基类(也可以称之为抽象类)。对于所有你想要“抽象”的方法,在.m文件中实现它们,而不是在.h文件中实现。 让你的子类继承基类并实现协议。
这样,编译器就会对协议中没有由你的子类实现的任何方法发出警告。
它不像Java中那样简洁,但您确实会得到所需的编译器警告。
Typically, Objective-C class are abstract by convention only—if the author documents a class as abstract, just don't use it without subclassing it. There is no compile-time enforcement that prevents instantiation of an abstract class, however. In fact, there is nothing to stop a user from providing implementations of abstract methods via a category (i.e. at runtime). You can force a user to at least override certain methods by raising an exception in those methods implementation in your abstract class:
[NSException raise:NSInternalInconsistencyException
format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
如果您的方法返回一个值,那么使用起来会更容易一些
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
这样就不需要从方法中添加return语句了。
如果抽象类实际上是一个接口(即没有具体的方法实现),使用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 -模板方法模式?
通过应用@dotToString的评论,稍微改变一下@redfood的建议,你实际上得到了Instagram的IGListKit所采用的解决方案。
为所有在基(抽象)类中定义没有意义的方法创建一个协议,即它们需要在子类中特定的实现。 创建一个不实现此协议的基(抽象)类。您可以向该类添加任何其他具有公共实现的方法。 在项目中的任何地方,如果必须通过某种方法输入或输出AbstractClass的子对象,请将其键入为AbstractClass<Protocol>。
因为AbstractClass没有实现Protocol,所以拥有AbstractClass<Protocol>实例的唯一方法是子类化。由于AbstractClass不能单独在项目中的任何地方使用,因此它变得抽象。
当然,这并不能阻止不明智的开发人员添加简单地引用AbstractClass的新方法,这最终将允许抽象类的实例(不再是)。
真实世界的例子:IGListKit有一个基类IGListSectionController,它不实现协议IGListSectionType,但是每个方法都需要这个类的实例,实际上要求类型IGListSectionController<IGListSectionType>。因此,在框架中没有办法使用IGListSectionController类型的对象来做任何有用的事情。