Ios 创建更好的面向对象设计

Ios 创建更好的面向对象设计,ios,objective-c,Ios,Objective C,我有以下课程: Teacher Student Class (like a school class) 它们都是从具有以下代码的KObject扩展而来: - initWithKey - send - processKey 教师、学生类都使用来自KObject父类的函数processKey和initWithKey。他们实现了自己版本的send。我的问题是KObject永远不应该被实例化。它更像一个抽象类,但objective-c中没有抽象类概念。它只在允许子类访问一个属性和两个函数时有用 我该

我有以下课程:

Teacher
Student
Class (like a school class)
它们都是从具有以下代码的KObject扩展而来:

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

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

一个黑客解决方案:

- (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; }
最好使用协议将“发送”作为一种抽象方法…

一种黑客解决方案:

- (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; }

最好使用协议将“send”作为抽象方法…

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

因为您编写的抽象类在Objective-C中不受支持,所以您很可能不应该尝试“修复”它。Objective-C不像其他语言(如C++/Java/C-Sharp语言)那样构建,并且不支持这些语言的某些功能。因此,在编写“Objective-C”代码时,不要试图用“Objective-C”来编写“Java with Objective-C”,而是要接受差异,并尝试用“Objective-C”的方式来编写代码对于其他试图使用或维护您的代码的程序员来说,这可能只会使其变得更难,而不是更容易。抽象类在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;
}
方法:

//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;
}
协议与抽象基础

我不同意在其他一些回答中提出的“最好使用协议”的说法。虽然可以将抽象基类与协议相结合,但并不一定更好

何时使用协议

使用协议来指定集成契约-就像插件体系结构一样。例如,“媒体播放器”,其中电影音频流的“播放”实现将完全不同

何时使用抽象基类(或类集群)

当类层次结构之间的某些行为是共享的,并且某些实现细节因特定子类型而异时,请使用抽象基类。在这里使用协议并不一定更好,除非您希望传达这样一种意图,即这组方法可以替换为另一个实现

类群集:

//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中的抽象类相关的一个有趣点)

抽象类在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;
}
方法:

//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;
}
协议与抽象基础

我不同意在其他一些回答中提出的“最好使用协议”的说法。虽然可以将抽象基类与协议相结合,但并不一定更好

何时使用协议

使用协议来指定集成契约-就像插件体系结构一样。例如,“媒体播放器”,其中电影音频流的“播放”实现将完全不同

何时使用抽象基类(或类集群)

当类层次结构之间的某些行为是共享的,并且某些实现细节因特定子类型而异时,请使用抽象基类。在这里使用协议并不一定更好,除非您希望传达这样一种意图,即这组方法可以替换为另一个实现

类群集:

//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中的抽象类相关的一个有趣点)

此类问题可能更适合于我不确定我是否理解您的问题。你在写程序,对吗?所以,永远不要实例化KObject。为什么你认为你需要使它无法实例化?顺便说一下,不要给你的类命名
class
!这是一种保留的Objective-C类型。命名它
学校班级