在单个NSMutableArray中管理不同类的对象

时间:2012-03-16 03:31:25

标签: objective-c arrays object pointers

我正在寻找关于这是否是一个好习惯的建议。我为长篇解释道歉。我有一个大的x,y坐标网格。网格由不同类的对象占用,所有对象都有不同的方法和数据。当用户触摸网格坐标时,我正在寻找最简单的方法将程序路由到正确的方法,具体取决于对象类型。

我将使用形状作为解释我正在做的事情的简单方法。假设我有两个类,Circle和Square都有一个父类Shape。

我将Circle类和Square类的对象添加到名为shapeManager的NSMutableArray中。当用户触摸网格时,我想找出该坐标的对象类型,以便我可以路由到适当的方法。

for (Shape *shape in shapeManager) {

  if (shape.type == kCircle) {

    [self circleSelected:shape];

  }

}

-(void)circleSelected:(circle *)circle { }

当我这样做时,我是否将指针改为另一个类?这有什么缺点吗?我只是在寻找一种处理网格上的触摸事件的好方法,当生活在该坐标处的对象是未知的并且具有多个可能的类时。

3 个答案:

答案 0 :(得分:0)

NSObject派生的所有类都继承了一个名为isMemberOfClass:的方法,该方法将使用内省测试类成员资格。您可能会发现这对您的目的很有用。

for (Shape *shape in shapeManager) {

    if ([shape isMemberOfClass:[Circle class]]) {   
        [self circleSelected:(Circle*)shape];
    }
    else if ([shape isMemberOfClass:[Square class]]} {
        [self squareSelected:(Square*)shape];
    }
}

还有一个isKindOfClass:方法执行类似的测试,但如果接收对象是您要测试的类的子类,也会返回true。

答案 1 :(得分:0)

如何实施'选择' Shape的子类中的方法,它是Circle和Square类。然后,该对象可以调用“已选择”#39;方法直接。

for (Shape *shape in shapeManager) {
    [self selected];
}

圈子实施

@interface Circle: Shape
{
}
@implementation Circle
-(void)selected
{
    // do your circle select stuff here
}

@end

方形实施

@interface Square: Shape
{
}
@implementation Square
-(void)selected
{
    // do your square select stuff here
}

@end

答案 2 :(得分:0)

如果您添加另一个Shape,您的方法的缺点就是 - 您最终必须更改此代码。另一种方法是向userSelected类添加一个方法,比如Shape,让每个子类重写此方法,以执行适合于它们所代表的形状的任何方法。

在另一种方法中,你的循环变为:

for(Shape *shape in shapeManager)
   [shape userSelected];

例如,Circle获得了一种方法:

@implementation Circle

// override Shape's userSelected and do what a circle needs to do
- (void) userSelected
{
   ...
}

您选择哪种方法取决于您,没有正确回答本身,但面向对象的风格通常有利于后者。

评论跟进

从孩子到父母,你不需要演员,但可以包括一个 - 这是基于继承的面向对象语言的基础,如Obj-C。

另一方面,从父母到孩子,在Obj-C(a)中需要演员和(b)应该受到支票的保护 - 因为你不知道孩子中的哪一个(如果有的话)有。在Obj-C(a)中告诉编译器你认为你知道它应该信任你,(b)你是否在检查以确保它!

您(b)与[<obj> isKindOfClass:[<classname> class]一起测试<obj>是否属于<classname> 的任何子女;或者您可以使用isMemberOfClass来测试<obj>类型<classname> 的任何子项。前者更容易扩展(例如,您可以从Rectangle开始Shape开始,然后将Square作为Rectangle; isMemberOfClass:[Rectangle class]的测试对于YESRectangle,{}}} Square isKindOfClass:[Rectangle class] YES只有Rectangle

通常不需要显式测试,因为方法调度通常包含它 - 如上面的[shape userSelected],它将在运行时根据userSelected的实际类型调用shape的适当实现。当需要使用测试进行显式测试时,可以使用强制转换。

是的,混合类型的集合很常见,实际上它们是基于继承的面向对象语言(如Obj-C)的另一个板块。

[注意:Obj-C缺少哪些其他语言是限制集合可能包含的内容的方式。例如。 NSMutableArray可以包含任何对象,而在您的情况下,能够说NSMutableArray of Shape将其限制为Shape及其子类可能是有益的。 C#,Ada,甚至C ++(尽管它强制执行任何东西)都提供了这一点。如果您需要,您可以在Obj-C中自己完成,请参阅this answer。]