如何扩展 NSArray?

发布于 2024-12-28 12:18:06 字数 731 浏览 2 评论 0原文

这是我的尝试:

H file:

@interface Strings : NSArray
@end

M file:

@implementation Strings
- (id) init
{
    [self initWithObjects:
     @"One.",
     nil];
    return self;
}
@end

当我运行时,我得到这个:

'NSInvalidArgumentException', Reason: '* -[NSArray initWithObjects:count:]: 仅为抽象类定义的方法。定义 -[Strings initWithObjects:count:]!'

这就是我所做的:

H 文件:

@interface Strings : NSObject
+ (NSArray*) getStrings;
@end

M 文件:

@implementation Strings
+ (NSArray*) getStrings
{
    NSArray* strings = [[NSArray alloc] initWithObjects:
     @"One.",
     nil];
    return strings;
}
@end

Here's my try:

H file:

@interface Strings : NSArray
@end

M file:

@implementation Strings
- (id) init
{
    [self initWithObjects:
     @"One.",
     nil];
    return self;
}
@end

When I run I get this:

'NSInvalidArgumentException', reason: '* -[NSArray initWithObjects:count:]: method only defined for abstract class. Define -[Strings initWithObjects:count:]!'

This is what I did instead:

H file:

@interface Strings : NSObject
+ (NSArray*) getStrings;
@end

M file:

@implementation Strings
+ (NSArray*) getStrings
{
    NSArray* strings = [[NSArray alloc] initWithObjects:
     @"One.",
     nil];
    return strings;
}
@end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

甜心 2025-01-04 12:18:06

NSArray 是一个 类簇(链接到Apple的文档)。这意味着当您尝试创建 NSArray 时,系统会创建 NSArray 的一些私有子类。 NSArray 类只是定义了一个接口; NSArray 的子类提供接口的实现。

您可以编写自己的 NSArray 子类,但必须为数组中的对象提供自己的存储。您必须自己初始化该存储。错误消息告诉您这一点,即您需要在子类中重写 initWithObjects:count: 。您的重写需要将对象放入您作为类实现的一部分分配的任何存储中。

可变参数 initWithObjects: 方法的 NSArray 实现只是 initWithObjects:count: 的包装,因此您不必实现 initWithObjects:

NSArray is a class cluster (link to Apple's documentation). This means that when you try to create an NSArray, the system creates some private subclass of NSArray. The NSArray class just defines an interface; subclasses of NSArray provide implementations of the interface.

You can write your own subclass of NSArray, but you have to provide your own storage for the objects in the array. You have to initialize that storage yourself. The error message is telling you this, by saying that you need to override initWithObjects:count: in your subclass. Your override needs to put the objects into whatever storage you allocate as part of your class implementation.

The NSArray implementation of the variadic initWithObjects: method is just a wrapper around initWithObjects:count:, so you don't have to implement initWithObjects:.

幸福不弃 2025-01-04 12:18:06

您应该避免从 NSArray 派生。从文档中:

请记住,NSArray 是类簇的公共接口,这对您的子类来说意味着什么。 NSArray 的原始方法不包含任何指定的初始值设定项。这意味着您必须为子类提供存储并实现直接作用于该存储的原始方法。

这意味着当您初始化数组时,您不会获得 NSArray 的实例。您将获得一个完全不同的类的实例,但它仅具有相同的接口。这就是为什么子类化并不像您想象的那样工作:您必须自己完全实现存储。这就是为什么文档进一步指出:

NSArray 的任何子类都必须重写原始实例方法 count 和 objectAtIndex:。这些方法必须对您为集合元素提供的后备存储进行操作。对于这个后备存储,您可以使用静态数组、标准 NSArray 对象或其他一些数据类型或机制。您还可以选择部分或全部覆盖您想要提供替代实现的任何其他 NSArray 方法。

最后但并非最不重要的一点是,无论如何你都会遇到初始化错误。您需要调用 super

- (id)init
{
    self = [super initWithObjects:@"One", @"Two", nil];
    if (!self) return nil;

    return self;
}

但正如我刚才所说,它并不那么容易工作。您将再次遇到相同的异常。因此,您应该避免从 NSArray 派生。

可以做的是添加一个类别来向所有NSArray实例添加方法。

Deriving from NSArray is something you should avoid. From the documentation:

Remember that NSArray is the public interface for a class cluster and what this entails for your subclass. The primitive methods of NSArray do not include any designated initializers. This means that you must provide the storage for your subclass and implement the primitive methods that directly act on that storage.

What this means is that when you initialize an array, you don't get an instance of NSArray. You'll get an instance of a totally different class that merely has the same interface. That is why subclassing doesn't work the way you think it works: you'll have to completely implement the storage yourself. This is why the documentation further states:

Any subclass of NSArray must override the primitive instance methods count and objectAtIndex:. These methods must operate on the backing store that you provide for the elements of the collection. For this backing store you can use a static array, a standard NSArray object, or some other data type or mechanism. You may also choose to override, partially or fully, any other NSArray method for which you want to provide an alternative implementation.

Last but not least you would have had the initializing wrong anyway. You would have needed to call super:

- (id)init
{
    self = [super initWithObjects:@"One", @"Two", nil];
    if (!self) return nil;

    return self;
}

But as I just said, it just doesn't work that easily. You'll get the same exception again. So you should simply avoid doing deriving from NSArray.

What you can do is add a category to add methods to all NSArray instances.

小清晰的声音 2025-01-04 12:18:06

NSArray 不支持以这种方式进行子类化。不过,您可以添加一个类别,尽管并不普遍推荐这样做。

有关更多想法,请参阅 Objective C - NSArray 子类

NSArray doesn't support being subclassed in this way. You can add a category, though, although that's not universally recommended.

See Objective C - Subclassing NSArray for more thoughts.

┈┾☆殇 2025-01-04 12:18:06

也许

self = [super initWithObjects:...];

perhaps

self = [super initWithObjects:...];
面如桃花 2025-01-04 12:18:06

您需要分配 self,并调用您的超类的 init 方法。

if (self = [super initWithObjects:...]) {
   ...
}

return self;

You need to assign self, and call your superclass' init method.

if (self = [super initWithObjects:...]) {
   ...
}

return self;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文