Iphone 处理来自不同类的对象

Iphone 处理来自不同类的对象,iphone,objective-c,Iphone,Objective C,我有3类对象。所有3个类共享一些共同的属性,如颜色、文本等 例如,我可以有这个 Class1 *objectA = [[Class1 alloc] init]; objectA.myColor = [UIColor redColor]; Class2 *objectB = [[Class2 alloc] init]; objectA.myColor = [UIColor redColor]; Class3 *objectC = [[Class3 alloc] init]; objectA.m

我有3类对象。所有3个类共享一些共同的属性,如颜色、文本等

例如,我可以有这个

Class1 *objectA = [[Class1 alloc] init];
objectA.myColor = [UIColor redColor];

Class2 *objectB = [[Class2 alloc] init];
objectA.myColor = [UIColor redColor];

Class3 *objectC = [[Class3 alloc] init];
objectA.myColor = [UIColor redColor];
。。。等等

例如,现在我需要创建一个方法来更改给定对象的颜色,不管它代表什么类

一个典型的方法是

- (void) changeColor:(Class1*) myOBJ toColor:(UIColor*)myColor {
   myOBJ.color = myColor;
}
事实上我需要这个

- (void) changeColor:(???) myOBJ toColor:(UIColor*)myColor {
   myOBJ.color = myColor;
}
// what to put on ??? to make it generic? Is this a "whatever" kind?
谢谢

编辑 使用这种方法的问题

- (void) changeColor:(id)myOBJ toColor:(UIColor*)myColor {
   if ([myOBJ respondsToSelector:@selector(setColor:)]) {
       myOBJ.color = myColor;
   }
}
是这个。假设我要设置对象的帧。 那我就得有这个:

- (void) changeColor:(id)myOBJ newFrame:(CGRect)myFrame {

 if ([umID isKindOfClass:[Class1 class]]) {
   Class1 *oneObj = (Class1 *)myObj;
   oneObj.frame = myFrame;
 }

 if ([umID isKindOfClass:[Class2 class]]) 
   Class2 *oneObj = (Class2 *)myObj;
   oneObj.frame = myFrame;
 }


 if ([umID isKindOfClass:[Class3 class]]) 
   Class3 *oneObj = (Class3 *)myObj;
   oneObj.frame = myFrame;
 }

}
换句话说,我将不得不重复同样的东西3次。。。对吧?


换句话说,这个问题没有解决,因为这与拥有3个方法相同,每个类一个方法。

???将是“id”。

???将是“id”。

您有几个选项。最简单也是最危险的方法是使用类型id。这将允许您传入任何对象,但您需要在尝试设置它之前测试它是否确实具有颜色属性

- (void) changeColor:(id)myOBJ toColor:(UIColor*)myColor {
   if ([myOBJ respondsToSelector:@selector(setColor:)]) {
       myOBJ.color = myColor;
   }
}
这就是说,通过响应选择器检查,这种方法并不那么危险,而且比下一种方法灵活得多

另一种方法是让所有对象从具有颜色属性的共享基类继承。那么您的参数类型将是基类。这种方法可以被认为更安全,因为编译器会检查您是否传入了正确类型的对象。这种方法还需要相当多的代码

如果您想使用第一种方法,但设置了颜色以外的内容,请适当地调整respondsToSelector:call

- (void) changeFrame:(id)myOBJ newFrame:(CGRect)myFrame {
   if ([myOBJ respondsToSelector:@selector(setFrame:)]) {
       myOBJ.frame = myFrame;
   }
}

通常,如果您想知道对象是否支持propertyX,请使用[myOBJ respondsToSelector:@selectorsetPropertyX:]。如果传入的对象声明为id,则可以调用[myOBJ setPropertyX:newPropertyValue]或myOBJ.propertyX=newPropertyValue。

您有两个选项。最简单也是最危险的方法是使用类型id。这将允许您传入任何对象,但您需要在尝试设置它之前测试它是否确实具有颜色属性

- (void) changeColor:(id)myOBJ toColor:(UIColor*)myColor {
   if ([myOBJ respondsToSelector:@selector(setColor:)]) {
       myOBJ.color = myColor;
   }
}
这就是说,通过响应选择器检查,这种方法并不那么危险,而且比下一种方法灵活得多

另一种方法是让所有对象从具有颜色属性的共享基类继承。那么您的参数类型将是基类。这种方法可以被认为更安全,因为编译器会检查您是否传入了正确类型的对象。这种方法还需要相当多的代码

如果您想使用第一种方法,但设置了颜色以外的内容,请适当地调整respondsToSelector:call

- (void) changeFrame:(id)myOBJ newFrame:(CGRect)myFrame {
   if ([myOBJ respondsToSelector:@selector(setFrame:)]) {
       myOBJ.frame = myFrame;
   }
}

通常,如果您想知道对象是否支持propertyX,请使用[myOBJ respondsToSelector:@selectorsetPropertyX:]。如果传入的对象声明为id,则可以调用[myOBJ setPropertyX:newPropertyValue]或myOBJ.propertyX=newPropertyValue。

也许可以使用协议?使Class1、Class2和Class3符合具有属性myColor的协议。然后,假设您的类是UIView类型,并且您的协议称为ColorProtocol,那么您可以有这样一个方法:

- (void) changeColor:(UIView<ColorProtocol>*) myOBJ toColor:(UIColor*)myColor {
   myOBJ.color = myColor;
   myOBJ.frame = ...;
}
@synthesize myColor;
按以下方式更改类定义文件.h,以指定您将遵守协议:

interface Class1 : UIView <ColorProtocol> {...}

如果您的类非常相似,那么使用继承可能更简单。看看Philip Regan的答案。

也许你可以使用协议?使Class1、Class2和Class3符合具有属性myColor的协议。然后,假设您的类是UIView类型,并且您的协议称为ColorProtocol,那么您可以有这样一个方法:

- (void) changeColor:(UIView<ColorProtocol>*) myOBJ toColor:(UIColor*)myColor {
   myOBJ.color = myColor;
   myOBJ.frame = ...;
}
@synthesize myColor;
按以下方式更改类定义文件.h,以指定您将遵守协议:

interface Class1 : UIView <ColorProtocol> {...}
如果您的类非常相似,那么使用继承可能更简单。查看Philip Regan的答案。

使用[object setFrame:newFrame];而不是object.frame=newFrame; 而不是oldFrame=object.frame;使用oldFrame=[对象帧]

使用[object setFrame:newFrame];而不是object.frame=newFrame;
而不是oldFrame=object.frame;使用oldFrame=[对象帧]

如果您有多个共享特性的类,那么,如果可能的话,我建议重构类结构,以便将这些特性包含在一个伞形父类中,我们称之为ClassZ。ClassZ的子类可以根据需要重写某些内容。否则,让父类中的方法为您处理它。然后,你的方法又变成了这个

- (void) changeColor:(ClassZ *) myOBJ toColor:(UIColor*)myColor {
   myOBJ.color = myColor; // note, myObj is ClassZ, not the subclasses.
}

否则,您将不得不使用id并测试单个类。

如果您有多个共享特性的类,那么,如果可能的话,我建议重构类结构,以便将这些特性包含在一个伞形父类中,我们将其称为ClassZ。ClassZ的子类可以根据需要重写某些内容。否则,让父类中的方法为您处理它。那么,哟 你的方法又变成了这个

- (void) changeColor:(ClassZ *) myOBJ toColor:(UIColor*)myColor {
   myOBJ.color = myColor; // note, myObj is ClassZ, not the subclasses.
}

否则,您将无法使用id并测试各个类。

无,但点表示法无法处理id类型的对象。这就是为什么object.frame=foo会导致编译错误,但[object setFrame:foo]编译并运行时没有任何问题。无,但是点表示法不适用于id类型的对象。这就是为什么object.frame=foo会导致编译错误,但[object setFrame:foo]编译并运行时没有任何问题。