【问题标题】:Dot Notation vs Method Notation点表示法与方法表示法
【发布时间】:2012-07-08 07:58:33
【问题描述】:

我正在深入研究 iOS 编程,但我很难理解点表示法和方法表示法的概念。

据我了解,点表示法可用于在属性上调用 setter/getter,并且写/读起来更干净。 Method Notation 用于向对象发送消息以对其进行操作等。

谁能给我一个简单的解释,为什么以下两个语句本质上不同,一个会编译,但另一个会因为语法错误而失败。

- (IBAction)digitPressed:(UIButton *)sender 
{
   NSString *digit = [sender currentTitle];

   self.display.text = [self.display.text stringByAppendingFormat:digit];
   self.display.text = self.display.text.stringByAppendingFormat:digit;

}

谢谢。

【问题讨论】:

  • 最后一行没有意义,有语法错误
  • 左边的项目不是字母吗,先生?
  • 我知道最后一行在语法上不正确,我正在寻找关于为什么这两行不同的解释。为什么方括号会改变 self.display.text 的含义?为什么我不能使用 self.display.text.stringByAppendingFormat?
  • 在一个表明您是 ObjC 初学者的问题中,您因使用无效代码而被否决,这令人担忧。您的问题可能更清楚(您通过省略表示最后一行代码已编译)但这就是我们在这里提供帮助的原因。
  • 不知道为什么这个问题被否决了,除了它的措辞不是很好。这里有一个问题,它实际上非常微妙,应该讨论。 Ricard 的回答是非常好的重新获取器/设置器和方法。 @Cirrostratus 的答案在方法方面非常有用。根据这些编辑您的问题,您就有了一个非常有用的问题。

标签: objective-c ios ios5


【解决方案1】:

您在一个有趣的时期进入 Objective-C 开发,旧语法与新语法一起使用。点语法是语法糖,在某些情况下你可以使用它,但你不应该使用它。

以下是无效的语法。任何使用冒号的地方(除了 setter 或 getter),都不会使用点表示法。

self.display.text = self.display.text.stringByAppendingFormat:digit;

另外,你会使用stringByAppendingString,而不是stringByAppendingFormat

您使用点符号来访问变量,而不是调用会产生影响的操作。

正确: self.foo.attributeOfMyClass

不正确: self.foo.downloadSomethingFromAWebsite

确保您始终使用点表示法来访问属性值,并且始终使用方括号表示法(即使您没有必须)调用操作方法,您的代码一看就会清楚很多。

【讨论】:

  • 以下语法无效。任何使用冒号的地方都不会使用点符号。
  • 这并不完全正确——注意[foo setBar:3]; 包含一个冒号,但可以用点表示法表示为foo.bar = 3;。重要的区别是点表示法可以用于访问器(获取或设置属性的方法),但不能用于其他任何东西。另请注意,如果它让您感到困惑,您根本不需要使用它。
  • 说得好,我完全同意
  • 我是唯一一个使用方法符号来解决异常崩溃的人吗?
【解决方案2】:

点表示法只是一种特定方法的简写——即访问器。您可以在以下情况下使用它:

  1. 设置属性时:foo.bar = 3; 等价于[foo setBar:3];
  2. 请求属性时:除上述情况外,foo.bar 等价于[foo bar]

点表示法只是的简写——它与属性的关系没有什么神奇之处。您可以理论上使用点符号来发送任何不带参数的消息 (foo.doSomething),但这将是非常非常糟糕的样式,因为点符号是为属性设计的.另请注意,如果点符号与方括号在您学习时让您感到困惑,那么完全避免点符号是一个完全有效的选择。如果您愿意,这只是您可以用于访问器的一种快捷方式。

【讨论】:

    【解决方案3】:

    实际上,您的第二个陈述是不正确的。调用方法(消息)的 Objective C 方法是使用 [instance message] 语法。 正如你所说,点符号只是调用类属性的getter和setter,而不是消息,这就是你的第二个陈述不正确的原因。您可能想要比较的两行是:

    self.display.text = [self.display.text stringByAppendingFormat:digit];
    [[self display] setText:[[[self display] text] stringByAppendingFormat:digit]];
    

    请注意,消息 stringByAppendingFormat 必须以正常方式调用。 点表示法只是为了写得更快,没有那么多括号,但编译后会执行完全相同的指令。

    【讨论】:

    • 所以点符号的主要功能纯粹是用于设置/获取,如果我想操作对象我应该使用方法符号吗?我来自 Java 背景,所以使用 (.) 来操作变量/对象是我的习惯,所以我可能会感到困惑。
    • 就是这样。一开始有点乱,但你会喜欢它! :)
    • @Darryl:(据我所知)在 Java 中,方法比在 ObjC 中更多是其对象的“成员”。这里有一个额外的间接步骤——你向一个对象发送一条消息,该对象由一个“选择器”组成,该对象在其元类的方法表中查找选择器。
    【解决方案4】:

    使用选择器表示法而不是点表示法的另一个原因是由于 Objective C 中的动态语言特性。例如,考虑以下情况:

    NSString *s = @"Hello World!";
    NSLog(@"Length is %d", s.length);
    

    这符合我们的预期。然而,Objective C 中的对象可以使用id 类型传递。考虑以下几点:

    id s = @"Hello World!";
    NSLog(@"Length is %d", s.length);
    

    这不会编译,因为id 没有名为length 的属性。但是,以下方法将起作用:

    id s = @"Hello World!";
    NSLog(@"Length is %d", [s length]);
    

    之所以可行是因为Objective C 知道NSString,因此知道有一些对象类型响应选择器length。当然,如果您尝试以下操作:

    id s = [[UIView alloc] init];
    NSLog(@"Length is %d", [s length]);
    

    您的代码将正确编译,但会发生运行时异常 (unrecognized selector sent to instance),因为 UIView 没有 length 选择器。

    【讨论】:

      【解决方案5】:

      假设我们有类Class 和变量variableOne,我们将使用这两种表示法。

      点符号是访问变量的最纯粹的方式。这也是括号符号最有可能在幕后进行的方式。通过键入Class.variableOne...variableOneClass 和“。”的一部分。在类告诉编译器它想要访问类的一部分——变量或方法之后。

      括号表示法是使用一种方法来访问变量。比方说……

      -(int) setVariable:x {
          self.variableOne = x;
      }
      
      -(int) showVariable {
          return self.variableOne
      }
      

      因此,当您使用括号表示法设置变量 [variableOne setVariable:5] 或显示变量 [variableOne showVariable] 时,它会调用适当的方法。

      这是考虑差异的一种非常简单的方法,我意识到另一个答案已经被接受,但也许这个答案会为不理解另一个答案的人解释它。

      【讨论】:

      • 说得好,自从我发布这篇文章以来,我在 Objective-C 的细微差别方面获得了更多经验,但回头看看旧问题的替代答案总是很高兴。
      【解决方案6】:

      当您的代码被编译时,clang 实际上首先将您的所有点表示法转换为方法/括号表示法,因此self.display[self display] 完全相同。从 Objective-C 2.0 开始,点符号实际上是相当新的。只是为了方便。

      点表示法只能用于属性,因为像你试图做的事情(不会编译)会很麻烦:

      self.display.text.stringByAppendingFormat:digit;

      它也不适用于采用多个参数的方法,因为您需要在参数之间放置空格,并且突然之间代码行会显得笨拙且难以阅读。

      【讨论】:

      • 点表示法实际上可以用于任何无参数方法 (tableView.reloadData;),并且可以在编译器找到对应的 setter (myMutableString.string = @"Excelsior!";) 的任何时候像左值一样使用,但事实并非如此有利于阅读/维护能力。
      • Josh 是对的,它适用于任何无参数方法。它应该只用于访问器。我想补充一点,这不仅包括用@property 定义的方法,还包括任何-property-setProperty: 形式的方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-30
      • 1970-01-01
      • 2010-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多