3

我在这里做了什么?方法参数可以是无类型的吗?

在最近一个运行良好的项目中,该应用程序已经在商店中 - 到目前为止没有问题,我在 .h 文件中执行了以下操作:

@property (strong, nonatomic) NSManagedObject          *myPerson;
- (HKPersonPicker*) initWithPerson:person;
- (HKPersonPicker*) initWithPerson:person delegate:(id <HKPersonPickerDelegate>)delegate;

我打算这样做,但没有:

- (HKPersonPicker*) initWithPerson:(NSManagedObject*)person;
- (HKPersonPicker*) initWithPerson:(NSManagedObject*)person delegate:(id <HKPersonPickerDelegate>)delegate;

.m 文件的对应部分:

- (HKPersonPicker*) initWithPerson:person
{
    self = [super init];
    if(self){
        self.myPerson = person;
    }
    return (self);
}

- (HKPersonPicker*) initWithPerson:person delegate:(id <HKPersonPickerDelegate>)delegate
{
    self = [self initWithPerson:person];
    if(self){
        self.delegate = delegate;
    }
    return (self);
}

如您所见,我没有对这个人对象做任何特别的事情,只是将它分配给属性 myPerson。由于我没有调用任何对象的方法或访问它的数据,编译器不需要知道关于该对象的任何信息。但是从编译器的 ivew 角度来看是什么?输入身份证?只是什么?有没有默认类型?

如你所见,我没有任何真正的问题。我只是好奇。希望这个问题不会违反任何 SO 规则。

4

3 回答 3

3

对于 C,默认类型是int,但对于 Objective-C,它是id.

于 2013-03-06T20:41:27.427 回答
2

方法中缺少类型声明默认为id. IIRC,您可以在 Apple 的运行时库中看到大量没有返回类型的方法。

于 2013-03-06T20:42:01.647 回答
2

你正在做的事情没有明确的问题,但同时它也不是真正的犹太洁食。为了清晰起见,您仍然应该有一个类型声明,并保持良好且一致的类似 Cocoa 的代码样式。

所以它真的应该是这样的:

- (GSPersonPicker*) initWithPerson:(id)person;

你真的应该改变属性声明:

@property (strong, nonatomic) id *myPerson;

如果这没有改变,那么您的代码就会令人困惑。您知道将要输入的类型。因此,让编译器通过使用类型来帮助您处理有意义的警告/错误。您可能还应该使用“HKPerson”类型或您为实体命名的任何类型,因此编译器认为您不能传入“HKPlace”(它们都是“id”和“NSManagedObject”类型',这对你没有好处)

更重要的是,除非有理由,否则不应使用动态类型 (id)。编译器可以帮助您。错误和警告是你的朋友,它们告诉你搞砸了,而不是电脑。当你使用 'id' 时,编译器会运行,哦,任何东西都可以进入这里!!! 并且它不会检测到您向该方法发送会破坏一切的类型的错误。

现在假设您将使用多态性。IE,让我们为要遵守的多个类声明一个通用协议,它定义了我们的人:

@protocol GSPerson
-(NSUInteger)age;
@end

所以现在让我们定义几个类,并让它们订阅协议(胡萝卜降价之间的 GSPerson正在杀死我 atm lol):

#import "GSPerson.h"
@interface GSSpecialPerson <GSPerson>
// code
@end

#import "GSPerson.h"
@interface GSWeirdPerson <GSPerson>
// code
@end

然后让我们重新定义我们的方法签名以遵守协议:

- (GSPersonPicker*) initWithPerson:(id<GSPerson>)person;

还有我们的财产声明:

@property (strong, nonatomic) id <GSPerson> *myPerson;

现在编译器知道我传递给该方法的任何东西都应该符合我上面定义的 GSPerson 协议(即他们需要一个返回人员年龄的方法)。如果我尝试传递任何其他内容,它会抛出编译器警告,这很好。

更好的是,如果多态类缺少所需的方法,它会向它们发出警告。

于 2013-03-06T20:54:50.290 回答