【问题标题】:What's the difference between dot syntax and square bracket syntax?点语法和方括号语法有什么区别?
【发布时间】:2011-09-14 22:40:35
【问题描述】:

我正在经历一些 fpr Objective-C 的演练,并且我到了许多让我大吃一惊的地方。我很想把它们弄下来。

  1. 消息发送和方法调用有根本区别吗? Objective-C 让我两者都做:object.message 产生与[object message] 相同的结果。我认为可能无法使用点运算符策略创建嵌套消息?

  2. 我创建了一个NSArray 对象,现在我将使用NSEnumerator 打印结果:

    id myObject = [object objectEnumerator];

    在 while 循环中迭代并打印结果。 myObjecttypeid,这意味着它是在运行时解析的,而不是编译时解析的。我非常清楚我的NSArray 中存储了什么样的对象——它们是NSStrings——所以通过将myObject 的类型更改为 NSString * myObject,它工作得很好。但是,我进行了实验,发现myObject 可以是任何类型,无论是NSStringNSArray 还是NSEnumerator,这些都可以正常工作,完美地迭代NSArray 对象并产生相同的结果结果。 这是怎么回事?

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    我不确定您要在“消息发送”和“方法调用”之间做出什么样的区分,因为它们是描述同一事物的两种方式。点语法只是调用getter和setter的捷径,即:

    [foo length]
    foo.length
    

    完全一样,如下:

    [foo setLength:5]
    foo.length = 5
    

    在使用 getter 和 setter 时,通常应该只使用点语法;对所有其他方法调用使用方括号语法。

    对于第二个问题:这就是动态类型的工作原理。您在代码中添加的任何类型声明都是对编译器的提示;只要对象响应它们,您的 Objective-C 方法调用将始终有效。

    【讨论】:

    • 这里有一个很小且通常不相关的区别,因为对象接收到的消息可能不会导致调用同名的方法。
    • "在使用 getter 和 setter 时,您通常应该只使用点语法;对所有其他方法调用使用方括号语法。"为什么会这样?
    【解决方案2】:

    这是面向阅读您代码的人的区别。点语法表示状态(我正在访问一个 ivar),方法语法表示行为(我正在执行一些操作)。对于运行时来说,两者都是一样的。

    我认为 Apple 的意图是将访问器显示为您不应该担心的实现细节。即使它们可以触发副作用(由于访问器中的一些附加代码),它们通常也不会,因此抽象是不完美的但值得(恕我直言)。使用点表示法的另一个缺点是您并不真正知道它背后是否有结构或联合(与消息发送不同,在分配时永远不会触发副作用)。也许苹果应该使用与点不同的东西。 *shrugs*

    我认为可能无法使用点运算符策略创建嵌套消息?

    点表示法可用于嵌套调用,但请考虑以下几点:

    shu.phyl.we.spaj.da
    [[[[[shu]phyl]we]spaj]da]
    

    在这种情况下,越丑越好。两者都是代码异味,因为一个对象正在创建对远处另一个对象的依赖关系,但是如果使用方括号传递消息,您会从第二行获得额外可怕的语法,这使得代码异味更容易被注意到。同样,惯例是用点表示属性,用括号表示方法。

    【讨论】:

    • +1 表示“在这种情况下,越丑越好”。在实际有意义的上下文中。
    【解决方案3】:

    1:您的术语不正确。点运算符不是“方法调用”,是一种不同的操作。这只是消息发送的不同视觉外观。 [x y] 和 x.y 之间没有区别。不过,点语法只能接受一个参数,因为它仅用于属性访问。

    2:对象的静态(编译时)类型对其运行时的行为没有影响。即使您将其称为其他对象,您的对象仍然是 NSEnumerator。

    【讨论】:

    • 点符号可以用于 getter 和 setter。 [object setValue: 5] 与 object.value = 5 相同。你说得对,将它用于任何 getter 和 setter 都会自找麻烦。
    • 啊,是的。我应该澄清一下,而不仅仅是一揽子没有参数的描述。我会编辑帖子。
    【解决方案4】:

    1) 它们都是消息发送,只是语法不同。 [object message] 是传统语法,object.message 是“点符号”,但含义完全相同。你可以用点表示法做一些嵌套,但你不能用带有复杂参数的方法做任何事情。一般来说,老手 Obj-C 程序员不使用点表示法,除了简单的访问器调用。恕我直言。

    2) 运行时非常聪明,可以即时计算出来。指针的类型转换实际上只是编译器的一个线索,让你知道你什么时候搞砸了。当消息被发送到数组以获取值时(在这种情况下),这并不意味着什么。

    【讨论】:

      【解决方案5】:
      1. 消息发送是执行此操作的首选方式。这是社区使用并强化对象相互发送消息的概念,稍后当您开始使用选择器并询问对象是否响应选择器(消息)时,它就会发挥作用。

      2. id 基本上是一个指向任何东西的指针。这需要一些时间来适应,但它是 Objective-C 如何处理对象的动态类型的基础。当NSLog() 遇到%@ 格式说明符时,它会向应该替换令牌的对象发送description 消息(这在超类NSObject 中实现,并且可以在子类中覆盖以获得所需的输出)。

      将来当你这样做时,你可能会发现这样做更容易:

      for (NSString *s in YourNSArrayInstance) //assuming they are NSStrings as you described
      {
          NSLog(@"%@", s);
      }
      

      或者甚至只是:

      for (NSString *s in YourNSArrayInstance) //assuming they are NSStrings as you described
          NSLog(@"%@", s);
      

      你最终会学会喜欢发送消息。

      【讨论】:

        猜你喜欢
        • 2014-09-30
        • 2012-03-31
        • 2020-03-04
        • 1970-01-01
        • 1970-01-01
        • 2015-07-26
        • 2015-12-09
        • 1970-01-01
        相关资源
        最近更新 更多