口头禅: 如果某些东西很难(或者看起来需要比必要更多的代码),那么您的设计很可能与 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 中使用。维护起来会很痛苦。