5

我需要一个类,它具有 NSArray 的所有方法,它们的行为方式相同,但修改了 2 个方法。

我想在我的自定义类中覆盖这两种方法:

1) countByEnumeratingWithState:objects:count:

2)objectAtIndex:

经过数小时的研究,我没有看到任何合理的方法可以做到这一点,因为:

  • 我不想使用类别,因为并非所有 NSArray 实例都应该具有修改后的行为。(加上会引发警告)

  • 我不想重写所有初始化器加上所有 arrayWith... 方法 + 原始方法 + 实现了我自己的存储(因为这个功能已经在 Cocoa 中实现了,对吧?我为什么要重新实现一个已经存在的类?)

  • 如果我让我的自定义类继承 NSObject 并使用 NSArray 作为 ivar 中的存储,那么在 Xcode 中编程时所有 NSArray 的方法都不可用(即使我可以将它们转发到 NSArray ivar)

  • 我通过使用 method_setImplementation(...) 按需覆盖了一些方法实现,但仍然无法找到一种在运行时动态创建类的方法,然后将自定义实现我提到的 2 种方法。

期待你的想法!谢谢

4

2 回答 2

9

口头禅: 如果某些东西很难(或者看起来需要比必要更多的代码),那么您的设计很可能与 iOS / OS X 框架的设计原则背道而驰。它可能会产生更好的解决方案来重新审视您的设计。


要回答最初的问题,如果要继承 NSArray(或 NSMutableArray),则需要实现原始方法,不多也不少。

原始方法是在@interface类本身中声明的方法。IE:

@interface NSArray : NSObject
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index;
@end

对于 NSMutableArray:

@interface NSMutableArray : NSArray
- (void)addObject:(id)anObject;
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
- (void)removeLastObject;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
@end

如果您将 NSMutableArray 子类化并实现上述 7 个方法(也来自 NSArray 的两个),您将拥有一个与所有使用可变数组的 API 兼容的 NSMutableArray 子类(假设您的方法已正确实现)。

这是因为类集群的设计方式。公共类是抽象的;永远不会直接实例化。它们提供了一个原始接口,其中包含类的核心功能,然后是所有其他非原始 API 的具体实现(除了初始化程序,见下文),这些 API 是根据原语实现的。然后,具体的私有子类覆盖所有原语和一些非原语,以为特定配置提供最佳行为。

我想为我正在处理的库提供一个 NSArray 实例,并且我希望它对我的库的用户透明地工作。IE。对于他们来说,使用普通的 NSArray 和我将提供的修改后的类应该没有区别。IE。这是一个存储问题,最终用户不应该关心它,并且接口应该与 NSArray 保持相同 - 因此,此时失去所有 init 方法并不是一个真正的选择。

初始化方法不是原始接口的一部分NSArray。您正在添加一个超出文档定义的“使类与NSArray/兼容”的要求。NSMutableArray没有错,只是指出来。

之所以会出现这种情况,是因为将集合类子类化以提供您描述的那种业务逻辑非常罕见。集合的行为非常通用,而这种条件化集合行为的业务逻辑将在管理整个模型层对象图的类中完成。

如果您真的想这样做,请提供init*您想要的任何方法的实现,并根据需要调用您包装的通用实例。初始化器的实现并没有什么特别之处,这样做你会失去很多。

也不需要实现所有这些。实现一两个并@throw 其余的描述性异常。

如果您决定转发接受 var-args 的那些,则不能直接转发,因为没有 va_list 接受方法。相反,您需要将参数的 va_list 转换为语言数组(即id[] foo = malloc(... * sizeof(id));)并将其传递给initWithObjects:count:.

其他一些评论:

  • 您正在做的[在子类中提供完整的 NS*Array 接口] 似乎很难,因为它不是一种常见的模式,而且框架设计者认为没有必要创建支持它的设计。原始集合级别的自定义行为几乎总是在对象图中的更高级别更好地实现。 几乎总是。

  • method_setImplementation() 和动态类创建在学术上很有趣,但几乎从来都不是解决方案。显然,使用 NSArray 或 NSMutableArray 类(或具体的实现类)会破坏其他依赖标准行为的框架。除此之外,它是一种动态 OO 组合模式,并不真正打算在 Objective-C 中使用。维护起来会很痛苦。

于 2012-12-18T16:53:59.860 回答
0

与其继承 NSArray,为什么不基于 NSObject 创建一个包含 NSArray 的新类?

然后您可以使用 NSArray 的所有功能并添加您自己的方法来执行自定义操作吗?

或者你需要一个 NSArray?

于 2012-12-18T09:00:43.350 回答