我有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个方法相同,每个类一个。
答案 0 :(得分:4)
也许你可以使用协议?使Class1,Class2和Class3符合具有属性myColor的协议。然后你可以有这样的方法(假设你的类是UIView类型,你的协议叫做ColorProtocol):
- (void) changeColor:(UIView<ColorProtocol>*) myOBJ toColor:(UIColor*)myColor {
myOBJ.color = myColor;
myOBJ.frame = ...;
}
以下是您的协议定义:
@protocol ColorProtocol
@property (nonatomic, retain) UIColor *myColor;
@end
按如下所示更改类定义文件(.h)以指定您将符合协议:
interface Class1 : UIView <ColorProtocol> {...}
在实现文件(.m)中,您必须简单地合成myColor属性以符合ColorProtocol:
@synthesize myColor;
如果你的类非常相似,那么使用继承可能更简单。查看Philip Regan的回答。
答案 1 :(得分:3)
你有几个选择。最简单且“最危险”的方法是使用类型id
。这将允许您传入任何对象,但在尝试设置之前,您需要测试它实际上是否具有color
属性。
- (void) changeColor:(id)myOBJ toColor:(UIColor*)myColor {
if ([myOBJ respondsToSelector:@selector(setColor:)]) {
myOBJ.color = myColor;
}
}
(也就是说,响应选择器检查,这种方法并不是那么危险,而且它比下一个想法更灵活。)
另一种方法是让所有对象都从具有color属性的共享基类继承。然后您的参数类型将是基类。这种方法可以被认为是“更安全”,因为编译器会检查您是否传递了正确类型的对象。这种方法还需要更多代码。
如果您想使用第一种方法,但设置的不是颜色,请适当调整respondsToSelector:
来电。
- (void) changeFrame:(id)myOBJ newFrame:(CGRect)myFrame {
if ([myOBJ respondsToSelector:@selector(setFrame:)]) {
myOBJ.frame = myFrame;
}
}
通常,如果您想知道某个对象是否支持propertyX,请使用[myOBJ respondsToSelector:@selector(setPropertyX:)]
。如果传入的对象声明为id
,则可以调用[myOBJ setPropertyX:newPropertyValue]
或myObj.propertyX = newPropertyValue
。
答案 2 :(得分:2)
如果您有多个共享特征的类,那么,如果可能的话,我建议重构类结构,以便这些特性包含在伞形父类中,我们将其称为ClassZ
。 ClassZ
的子类可以根据需要覆盖事物。否则,让父类中的方法为您处理它。然后,你的方法又回到了这个......
- (void) changeColor:(ClassZ *) myOBJ toColor:(UIColor*)myColor {
myOBJ.color = myColor; // note, myObj is ClassZ, not the subclasses.
}
否则,您将遇到id
并测试各个类。
答案 3 :(得分:1)
使用[object setFrame:newFrame];
代替object.frame = newFrame;
而不是oldFrame = object.frame;
使用oldFrame = [object frame];
答案 4 :(得分:0)
???将是'id'。