我有以下课程:
Teacher
Student
Class (like a school class)
它们都来自具有以下代码的KObject:
- initWithKey
- send
- processKey
Teacher,Student Class都使用来自KObject父类的函数processKey和initWithKey。他们实现了自己的发送版本。我遇到的问题是KObject不应该被实例化。它更像是一个抽象类,但在objective-c中没有抽象类概念。它仅对允许子类访问一个属性和两个函数有用。
我能做什么才能使KObject无法实例化,但仍允许子类访问KObject的函数和属性?
答案 0 :(得分:5)
抽象类在Objective-C中非常常见, class cluster - Cocoa中广泛使用的模式 - 是抽象工厂模式的变体。
然而,正如您所指出的那样,没有语言工具可以将方法或类明确地划分为抽象 - 这通常在文档中完成。如果您需要额外的安全性以确保不以非预期的方式使用课程,您可以执行以下操作:
<强>初始化器:强>
//Invocation of the initializer in a sub-class will not raise the exception.
if ([self class] == [MyAbstractClass class])
{
[NSException raise: . . . class is abstract - use subclass.
}
方式:强>
- (BOOL)someAbstractMethod
{
[NSException raise:NSInvalidArgumentException format:@"%@ is abstract",
NSStringFromSelector(_cmd)];
return NO;
}
协议与抽象基础
我不同意声明“在一些其他答案中使用协议更好”。虽然可以将抽象基类与协议组合在一起,但它不一定更好。
何时使用协议
使用协议指定集成合同 - 就像插件架构一样。一个例子是“媒体播放器”,其中实现 电影 的“播放”和 音频 流将是完全不同的。
何时使用抽象基类(或类集群)
当共享类层次结构之间的某些行为时使用抽象基类,并且某些实现细节在特定子类型之间有所不同。 。在此处使用协议不一定更好,除非您希望传达这组方法可以替换为另一个实现的意图。
班级群组:
使用类集群工厂方法来获取其中一个子类的实例在基类本身上。有时,这会产生可读性和内聚性良好的代码。 (可能与您的具体示例无关,但与Objective-C中的抽象类相关的一个有趣点)
答案 1 :(得分:0)
一个hacky解决方案:
- (id)init { if ([self class] == [FastEnumerable class]) {
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"Error, attempting to instantiate KObject abstract class directly." userInfo:nil]; }
self = [super init]; if (self) {
// Initialization code here. }
return self; }
最好使用协议将“发送”作为抽象方法...
答案 2 :(得分:-1)
在Objective-C中不支持编写抽象类时,所以很可能不应该尝试“修复”它。 Objective-C的构建方式与c ++ / Java / C-Sharp语言等其他语言不同,不支持这些语言的某些功能。所以,而不是尝试编写“使用Objective-C的Java”来代替差异,并尝试在编写“Objective-C”时使用“Objective-C”方式,而不是做可能只会使其变得更难的黑客而不是对于试图使用或维护代码的其他程序员来说更容易。