2009-08-12 92 views
6

我创建了一个“SDMutableGrid”类,以便我可以使用网格。它只是NSMutableArray的一个子元素,其中包含的数组数等于网格中的行数。Objective C中的继承问题C

目前,程序在它真正开始之前就退出了,看起来这是因为为NSMutableArray定义的方法在某种程度上不适用于SDMutableGrid,任何人都知道为什么?

这里是.H:

#import <Foundation/Foundation.h> 
#import "SDDimensions.h" 

@interface SDMutableGrid : NSMutableArray { 
SDDimensions dimensions; 
} 

@property (nonatomic) SDDimensions dimensions; 

- (id)initWithDimensions:(SDDimensions)newDimensions; 
- (void)addObject:(id)anObject toRow:(NSUInteger)row; 

@end 

这里是.M:

#import "SDMutableGrid.h" 

@implementation SDMutableGrid 

@synthesize dimensions; 

- (void)setDimensions:(SDDimensions)newDimensions { 
if (newDimensions.width < dimensions.width) { 
    NSMutableArray *anArray; 
    NSRange aRange = NSMakeRange(newDimensions.width, dimensions.width - newDimensions.width); 
    for (NSUInteger i = 0; i < MIN(dimensions.height,newDimensions.height); i++) { 
     anArray = [self objectAtIndex:i]; 
     [anArray removeObjectsInRange:aRange]; 
    } 
} 
dimensions.width = newDimensions.width; 
if (newDimensions.height > dimensions.height) { 
    for (NSUInteger i = dimensions.height; i < newDimensions.height; i++) { 
     [self addObject:[[NSMutableArray alloc] initWithCapacity:dimensions.width]]; 
    } 
} else if (newDimensions.height < dimensions.height) { 
    [self removeObjectsInRange:NSMakeRange(newDimensions.height, dimensions.height - newDimensions.height)]; 
} 
dimensions.height = newDimensions.height; 
} 

- (id)initWithDimensions:(SDDimensions)newDimensions { 
if (self = [super initWithCapacity:newDimensions.height]) { 
    NSMutableArray *anArray; 
    for (NSUInteger i = 0; i < newDimensions.height; i++) { 
     anArray = [[NSMutableArray alloc] initWithCapacity:newDimensions.width]; 
     NSLog(@"Got this far"); 
     [self addObject:anArray]; 
     NSLog(@"woot"); 
     [anArray release]; 
    } 
    NSLog(@"Finished Initializing grid"); 
} 
return self; 
} 

- (void)addObject:(id)anObject toRow:(NSUInteger)row { 
    [[self objectAtIndex:row] addObject:anObject]; 
} 

@end 

,这里是什么出现在控制台上:

2009-08-12 15:27:02.076 Flipswitch [1756:20b] 由于未捕获异常'NSInvalidArgumentException'而终止应用程序,原因:' - [NSMutableArray initWithCapacity:]:仅为抽象类定义的方法。定义 - [SDMutableGrid initWithCapacity:]!' 2009-08-12 15:27:02.080 Flipswitch [1756:20B]堆栈:( 807902715, 2536648251, 808283725, 808264737, 13690, 11018, 10185, 814713539, 814750709, 814739251, 814722434, 814748641, 839148405, 807687520, 807683624, 814715661, 814752238, 10052,)

回答

37

简而言之,简单的答案:不要创建NSArray的子​​类。最好在NSArray上创建一个类别,或者创建一个NSObject子类,该子类具有与您交谈的NSArray ivar。

长,技术答案:NSArray是class cluster。这意味着它实际上不是一个类,但是在NSArray抽象类接口下运行的许多类都以不同的方式实现(例如,一个用于小型阵列的实现,另一个用于大型阵列等)。要创建类集群的子类,您必须实现您所继承的抽象类的所有原始方法,管理您自己的存储并基本上重新实现您希望通过子类化免费获得的所有内容。

更简单地说,如果您不需要额外的ivars,您可以创建一个类别。如果你想要一个具有额外状态的数组的行为,你可以创建一个具有NSArray的类,并使用Objective-C消息转发将除你的自定义行为之外的所有内容转发给该类。

+0

+1我想补充说,将NSArray包装在NSObject子类中的第一个例子叫做**组合类** – 2010-11-15 01:49:17

2

好吧,我发现从this question

答案虽然问题是不同的,答案是相同的,那就是,由于NSArray的(因此NSMutableArray的)的设置,你不能没有实现的方法继承它你自己。

所以我想我只是让SDMutableGrid有一个NSMutableArray变量,而不是实际上是一个NSMutableArray。

+0

是的检查我的答案 – Daniel 2009-08-12 19:49:59

+0

检查所有的答案,那些是一些快速的回应。 – Joe 2009-08-12 20:10:02

2

你问题在于你没有实现需要实现的NSMutableArray超类的抽象方法,它说 - [NSMutableArray initWithCapacity:]:方法只针对抽象类定义。定义 - [SDMutableGrid initWithCapacity:]!' 2009-08-12 15:27:02.080 Flipswitch [1756:20b]

所以你需要在你的子类中定义initWithCapacity,我建议不要扩展NSMutableArray,没有必要,只需要创建一个类可变数组。

7

这是由于用于基金会收集课程的'班级集群'的性质。 请参阅: Class Clusters

基本上,NSMutableArray中定义了一个公共接口“可变阵列”,而不是在初始化时你实际使用的类。所以定义了'initWithCapacity:',但是没有在NSMutableArray中实现。如果你运行:

NSMutableArary *foo = [[NSMutableArray alloc] init]; 
NSLog(@"%@", [foo className]); 

您将打印 “_NSCFArray”,这是NSMutableArray的(和的NSArray)的具体子类。要解决这个问题,我需要一个实例变量,它是一个NSMutableArray,或者实现具有合适含义的“initWithCapacity:”(例如“3”意味着3x3网格)。