2

我有以下课程:

Teacher
Student
Class (like a school class)

它们都从具有以下代码的 KObject 扩展而来:

- initWithKey
- send
- processKey

教师、学生类都使用 KObject 父类的函数 processKey 和 initWithKey。他们实现了自己的发送版本。我遇到的问题是永远不应该实例化 KObject 。它更像是一个抽象类,但是objective-c中没有抽象类的概念。它仅对允许子类访问一个属性和两个函数有用。

我该怎么做才能使 KObject 无法实例化但仍允许子类访问 KObject 的函数和属性?

4

3 回答 3

5

抽象类在 Objective-C 中很常见,而类簇——在 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 中的抽象类有关的一个有趣点)

于 2013-10-20T07:45:55.077 回答
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; }

并且最好使用协议将“发送”作为抽象方法......

于 2013-10-20T01:47:51.423 回答
-1

正如您所写的,Objective-C 不支持抽象类,因此您很可能不应该尝试“修复”它。Objective-C 不像其他语言(如 c++/Java/C-Sharp 语言)那样构建,并且不支持这些语言的某些功能。因此,与其尝试编写“使用 Objective-C 的 Java”,不如拥抱差异,并在编写“Objective-C”时尝试以“Objective-C”的方式做事,而不是做黑客,这可能只会使其更难而不是其他程序员尝试使用或维护您的代码更容易。

于 2013-10-20T07:41:01.113 回答