【问题标题】:objective c operator precedence目标 c 运算符优先级
【发布时间】:2015-03-13 11:36:44
【问题描述】:

如果我讨厌一件事,那就是在没有完全理解其背后的逻辑的情况下,就这样走了,所以....我偶然发现了这个表达:

 MSClient *client = [(AppDelegate *) [[UIApplication sharedApplication] delegate] client];

我实际上一直使用点语法来编写对变量的访问,并且仅将硬括号用于方法调用,但我想这只是喜欢的任何一种。我的困惑在于我通常会这样写:

 MSClient *client = ((AppDelegate *) [[UIApplication sharedApplication] delegate]).client;

因为这行不通:

     MSClient *client = (AppDelegate *) [[UIApplication sharedApplication] delegate].client;

由于演员表没有应用于正确的对象,我想知道第一个书面表达式如何顺利编译而没有任何错误,因为在我看来,演员表没有括在括号中,并且适用于“委托”;它应用最外面的硬括号,删除“。”并删除使第 3 个表达式起作用的括号,而第 2 个则不起作用。

唷,很抱歉就这么简单的事情发表了长篇文章。但同样,我讨厌在没有完全理解的情况下顺其自然。

谢谢!

【问题讨论】:

  • [[UIApplication sharedApplication] delegate] 视为X,那么该表达式将类似于[(AppDelegate *)X client]; 而不是(AppDelegate *)[X client];
  • 是的,但是在第二个表达式中,没有额外的 (......delegate]) 时出现错误。 ;如果没有额外的 () 仍然会给 (AppDelegate *)X.client = [(AppDelegate *)X client];对吗?

标签: ios objective-c


【解决方案1】:

这是因为 C(或 Objective-C,在这种情况下)中的运算符优先级:

(AppDelegate *) [[UIApplication sharedApplication] delegate].client

点运算符. 的绑定比强制转换运算符(AppDelegate*) 更强。首先,客户端被获取,然后被强制转换。因此它等价于

(AppDelegate *)([[UIApplication sharedApplication] delegate].client)

用我自己的话来说:

  • clientMSClient 实例引用)的返回类型被强制转换为 AppDelegate 实例引用。
  • delegate (NSObject <NSApplicationDelegate>) 的返回类型未强制转换为任何内容。

工作方式改变了演员的主题:

((AppDelegate *)[[UIApplication sharedApplication] delegate]).client;

使用括号明确表示委托的返回值是强制转换的主题。

人们可能会认为点运算符的不同优先级可以解决这个问题。但这会在其他情况下导致丑陋的可能。使用优先级来提高代码的可读性是很脆弱的。

我不认为这真的是一个问题。如果它适合你,你可以简单地添加一个额外的方法 -appDelegateUIApplication,它具有正确的类型:

@interface UIApplication (MyAddition)
- (AppDelegate*)appDelegate;
+ (AppDelegate*)appDelegate;
@end

@implementation UIApplication (MyAddition)
- (AppDelegate*)appDelegate
{
  return (AppDelegate*)self.delegate;
}

+ (AppDelegate*)appDelegate
{
  return (AppDelegate*)[[self sharedApplication] delegate];
}

每个项目只限一次。

你可以这样使用它:

… [UIApplication sharedApplication].appDelegate.client … // -appDelegate
… [UIApplication appDelegate].client …                   // +appDelegate

在 Safari 中输入。

【讨论】:

  • 每个项目一次是什么意思?无论如何,谢谢您的彻底答复。代码 sn-p 有点令人困惑,关于优先级的解释确实足够且令人满意。 ty
  • 您必须为每个项目添加一次该代码(更准确地说:为每个应用程序委托,但通常每个项目有一个)并摆脱该项目中的所有演员表。为什么你被 sn-p 弄糊涂了?
  • 好吧,我想这很明显,你必须在每个项目中都这样做^^我想我有点困惑,因为公共和私有方法不会进行完全相同的调用。另外,当我像这样覆盖 UIApplication 时,我是否总是必须在应用程序委托中这样做?
  • 为什么不用私有方法调用sharedApplication?
  • 我想说您只需必须为每个项目添加一次代码。 (而不是每个项目有几十个铸件)。
【解决方案2】:

似乎接受的答案实际上并没有解决这个问题。你问这是为什么:

MSClient *client = [(AppDelegate *) [[UIApplication sharedApplication] delegate] client];

编译“因为在我看来演员没有被括号括起来,并且适用于“代表””。

在该表达式中,强制转换只能应用于[[UIApplication sharedApplication] delegate] 的结果。这是它之前的唯一完整子表达式。它不能应用于-client message-send 表达式的结果,因为该 message-send 表达式从第一个左括号开始,并且演员表在其中。

在这里,我举例说明如何分解表达式:

[v----------------subexpression for receiver----------------v client]
 (AppDelegate *) [v---subexpression for receiver--v delegate]
                  [UIApplication sharedApplication]

强制转换的语法是它出现在子表达式之前并修改该子表达式的类型。在这种情况下,它修改了上述行的中间部分。它不能修改第一个,因为这样做必须在它之前——在第一个左括号之前——而它没有。它不能修改第三个,因为从中间子表达式开始的第二个左括号位于强制转换和第三个子表达式之间。转换不会立即在第三个子表达式之前。

【讨论】:

    猜你喜欢
    • 2013-02-24
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 2013-07-31
    • 1970-01-01
    • 2013-02-09
    相关资源
    最近更新 更多