这是 运行 通用方法的正确方法吗?

Is this the right way to run a generic method?

我有这个方法应该设置对象的名称,但对象可以是 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];
  } 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 而我们又回到了原点。同样的错误。

我有什么 better/elegant 方法可以做到这一点?

更好的方法是让 ABC 实现相同的 protocol,这将定义一个方法 setName.

NameProtocol.h

@protocol NameProtocol <NSObject>

- (void)setName:(NSString *)name;

@end

A.h

@interface A : NSObject <NameProtocol>

B.h

@interface B : NSObject <NameProtocol>

C.h

@interface C : NSObject <NameProtocol>

使用 class A、B 和 C 都遵守的协议。

@protocol MyProtocol <NSObject>
@required
- (void)setName:(NSString *)name;
@end

然后

id<MyProtocol> object = ...
[object setName:newName];

协议是必经之路。但你也可以这样做:

if ([object respondsToSelector: @selector(setName:)])
{
    [object performSelector: @selector(setName:) withObject: name];
}

使用键值编码。

[object setValue:newName forKey:@"name"];

这是一种快速而肮脏的方法,我建议使用协议,但在适当的情况下它会很有用。


更新

KVC 没有编译时类型检查:增加了出现缺陷的可能性。运行时错误导致异常:缺陷导致应用程序崩溃。它的语法暗示 object 是一个字典:隐藏代码的意图。晦涩难懂:初级开发人员通常不会理解它是如何工作的,并且可能会导致维护问题。

这是一部真正的恐怖片,但在适当的情况下会很有用。