Ios 这是运行泛型方法的正确方法吗?
我有这个方法,应该设置对象的名称,但是对象可以是3个类,A、B和C 如果我这么做的话Ios 这是运行泛型方法的正确方法吗?,ios,objective-c,macos,cocoa,cocoa-touch,Ios,Objective C,Macos,Cocoa,Cocoa Touch,我有这个方法,应该设置对象的名称,但是对象可以是3个类,A、B和C 如果我这么做的话 [object setName: @"new name"]; //at this point I am treating object as of type id Xcode会抱怨有多个名为“setName”的方法,然后我就这样做了 if ([object isKindOfClass:[ClassA class]]) { [(ClassA *)object setName:newName];
[object setName: @"new name"]; //at this point I am treating object as of type id
Xcode会抱怨有多个名为“setName”的方法,然后我就这样做了
if ([object isKindOfClass:[ClassA class]]) {
[(ClassA *)object setName:newName];
} else
if ([object isKindOfClass:[ClassB class]]) {
[(ClassB *)object setName:newName];
} else
[(ClassC *)object setName:newName];
}
但这在我看来是站不住脚的
我试图用这样的东西愚弄Xcode
[(typeof(object))object setName:newName];
但是Xcode也不喜欢它,可能是因为typeof(object)
正在返回id
,我们又回到了原点。同样的错误
有什么更好/优雅的方法可以做到这一点呢?更好的方法是让
A
、B
和C
实现相同的协议
,该协议将定义一个方法setName
NameProtocol.h
@protocol NameProtocol <NSObject>
- (void)setName:(NSString *)name;
@end
@interface A : NSObject <NameProtocol>
@interface B : NSObject <NameProtocol>
@interface C : NSObject <NameProtocol>
@协议名称协议
-(void)setName:(NSString*)名称;
@结束
A.h
@protocol NameProtocol <NSObject>
- (void)setName:(NSString *)name;
@end
@interface A : NSObject <NameProtocol>
@interface B : NSObject <NameProtocol>
@interface C : NSObject <NameProtocol>
@接口A:NSObject
B.h
@protocol NameProtocol <NSObject>
- (void)setName:(NSString *)name;
@end
@interface A : NSObject <NameProtocol>
@interface B : NSObject <NameProtocol>
@interface C : NSObject <NameProtocol>
@接口B:NSObject
C.h
@protocol NameProtocol <NSObject>
- (void)setName:(NSString *)name;
@end
@interface A : NSObject <NameProtocol>
@interface B : NSObject <NameProtocol>
@interface C : NSObject <NameProtocol>
@接口C:NSObject
使用a类、B类和C类都符合的协议
@protocol MyProtocol <NSObject>
@required
- (void)setName:(NSString *)name;
@end
@protocol-MyProtocol
@必需的
-(void)setName:(NSString*)名称;
@结束
然后
id<MyProtocol> object = ...
[object setName:newName];
id对象=。。。
[对象集合名:newName];
协议是一条可行之路。但你也可以做到:
if ([object respondsToSelector: @selector(setName:)])
{
[object performSelector: @selector(setName:) withObject: name];
}
使用键值编码
[object setValue:newName forKey:@"name"];
这是一种快速而肮脏的方法,我建议使用协议,但在适当的情况下它可能会很有用
更新 KVC没有编译时类型检查:增加了缺陷的可能性。运行时错误导致异常:缺陷导致应用程序崩溃。它的语法意味着
对象
是一个字典:隐藏代码的意图。这一点很模糊:初级开发人员通常不了解它是如何工作的,并且可能会导致维护问题
这是一个真正的恐怖节目,但在适当的情况下它可能会很有用。声明的
对象是什么类型的?是否有多个名为setName
的方法?我们需要了解为什么会出现初始错误?是的,A、B和C类都有setName@LyndseyScott应用程序中还有其他类(甚至可能在CoreFoundation或其他一些Apple库中),它们对-setName:
具有不同的签名。我想就是这样!谢谢我会尽快接受你的回答,让我来。我本来也打算提出一个协议,但你抢先了我一步。另一种选择是为实现setName方法的所有3个类创建基类。您能描述一下这样做没有用的情况,这可能会导致问题吗?谢谢。@Unheilig添加了一些KVC攻击。谢谢,现在你让我对维护问题部分感到好奇。你能不能对这一部分再详细说明一下谢谢。@Unheilig使用重构工具重命名name
时,字符串@“name”
将不包括在内。更改关系时,您可能会错过这样设置的name
。