【问题标题】:Method parameter wihout type?没有类型的方法参数?
【发布时间】:2013-03-06 20:39:24
【问题描述】:

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

在最近的一个运行良好的项目中,应用程序已经在商店中 - 到目前为止没有问题,我在 .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 规则。

【问题讨论】:

    标签: objective-c


    【解决方案1】:

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

    【讨论】:

    • 原来如此。我确实在不知情的情况下依赖了一些默认值,并且纯粹出于运气,这没关系。不完全是我通常的风格,但很高兴知道。
    • 是的,就是这样;我认为,如果您访问该类的任何方法,在该方法中,编译器会对此感到不满,并且会更加明显。
    • 没错。既然你这么说......我应该尝试访问任何方法,编译器会告诉我它假设的实际类:“没有可见的 id 接口实现......” :)
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      所以它应该是这样的:

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

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

      @property (strong, nonatomic) id *myPerson;
      

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

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

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

      @protocol GSPerson
      -(NSUInteger)age;
      @end
      

      现在让我们定义几个类,并让它们订阅协议(胡萝卜之间的 GSPerson markdown 正在杀死我 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 协议(即他们需要一个返回人员年龄的方法)。如果我尝试传递任何其他内容,它会抛出编译器警告,这很好。

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

      【讨论】:

      • 感谢您的广泛回答。对此表示赞成。我完全同意。事实上,我是从那个项目中复制这段代码并在新项目中重新使用它。通过这样做,我注意到了这个耀斑。我不会将其更改为 id 而是更改为 NSManagedObject*,因为在新项目中,我不会从实体中生成模型类,而是使用 KVC。无论如何,谢谢。
      • 酷,学习新东西总是很高兴(在这种情况下,您使用 KVC,因此有理由在 person-specific 方法中使用 NSManagedObject 类型)
      • 我只是在尝试使用 KVC 能走多远。我当前的应用程序只是一个只有本地存储的小应用程序。有了这个应用程序,我没有从 KVC 中获得任何收益,但它并没有真正产生额外的努力等。到目前为止,这并不重要。下一个应用程序必须在本地复制使用 REST Web 服务的内容。当将 RestKit 对象的 KVC 与核心数据中的相同键结合起来时,我可能会收获很多。会看到...
      • 您可能希望谨慎使用 RESTKit,请在此处查看我的回答:stackoverflow.com/questions/14854641/… 我绝对建议您只推出自己的解决方案,尤其是如果您无法控制 REST api 的设计。
      • 谢谢,我去看看。但是,API 是“我的”。
      猜你喜欢
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多