在Objective-C中使用(id)

Jas*_*rge 7 objective-c

我有一个函数,我想在两个不同的自定义对象上操作.我的第一个想法是接受参数作为(id)并操作id对象.然而,我似乎无法弄清楚如何做到这一点.

这两个类(比如苹果和橙子)都有接口变量:

NSDecimalNumber *count;
Run Code Online (Sandbox Code Playgroud)

我想做类似的事情:

-(NSDecimalNumber*)addCount:(id)addObject{

    return [count decimalNumberByAdding:addObject.count];
}
Run Code Online (Sandbox Code Playgroud)

我似乎无法弄清楚实现这一目标的语法.这是正确的方法,还是从子类(从水果类)开始并对父类进行操作会更好?

-(NSDecimalNumber*)addCount:(Fruit*)addFruit{

    return [count decimalNumberByAdding:addFruit.count];
}
Run Code Online (Sandbox Code Playgroud)

LBu*_*kin 12

虽然您可以向任何对象(id)发送消息 - 属性访问器要求编译器知道您正在处理的类型 - 这是因为属性访问器是围绕调用特定getter和setter方法的语法糖.

你有几种方法可以解决这个问题:

  1. 不要访问count属性,而是调用相应的[getCount]方法.

  2. 如果不同的类具有此方法的不同版本,则可以使用运行时类型检查:

  3. 为这两种类型提供基类,以便您可以传递比(id)更具体的内容.

  4. 定义并实现两个对象实现的定义计数属性(或方法)的协议.

动态类型检查的示例:

if( [object isKindOfClass:[Apple Class] )
   // call one overload of getCount
else if( [object isKindOfClass:[Orange Class] )
   // call another overload of getCount
Run Code Online (Sandbox Code Playgroud)

就个人而言,我赞成在我的代码中强类型,因为这样可以更容易理解意图.它还允许IDE通过智能感知,静态分析和重构功能支持您的编码工作.因此,在您的情况下,我会使用#3或#4作为方法 - 取决于继承是否真的适合该问题.


pgb*_*pgb 8

您应该尝试不从另一个类访问实例变量.

在Objective-C中,两个对象响应相同的选择器(比如说count)就足够了,但这会给你一个编译器警告.

有两种方法可以消除此警告:通过从公共Fruit类继承或使您的两个类符合协议.我会使用协议:

@protocol FruitProtocol

- (NSDecimalNumber *)count;

@end

@interface Orange : NSObject<FruitProtocol>
@end

@interface Apple : NSObject<FruitProtocol>
@end
Run Code Online (Sandbox Code Playgroud)

然后你的方法看起来像这样:

-(NSDecimalNumber*)addCount:(id<FruitProtocol>)addFruit {
    return [count decimalNumberByAdding:[addFruit count]];
}
Run Code Online (Sandbox Code Playgroud)

在这里,您要说您addCount期望任何符合FruitProtocol协议的对象,因此可以响应count选择器,因此编译器将接受它.