【问题标题】:Why not start convenience constructors with "with"?为什么不使用“with”来启动便利构造函数呢?
【发布时间】:2009-06-19 12:18:29
【问题描述】:

我最喜欢 Cocoa 的一件事是可读性因素。

最让我烦恼的一件事是便利构造函数强制重复的约定。

这是一个例子:

[NSString stringWithString:s]

[NSNumber numberWithDouble:d]

[NSValue valueWithInt:i]

[NSDictionary dictionaryWithObjectsAndKeys:<blah>]

等等

为什么约定不简单地用单词“with”开始便利构造函数?那么我们将有:

[NSString withString:s]

[NSNumber withDouble:d]

[NSValue withInt:i]

[NSDictionary withObjectsAndKeys:<blah>]

等等

这是一个次要的讨论点,但我想我会扔在那里,看看是否有比我更有影响力的人可以解释我脑海中的所有回声。

显然,我不会请求 AAPL 重新编写 appKit 以支持我的建议,但是是否有反对将我自己的便利构造函数命名为这样的论点?

当然,我可以在自己的代码中使用我想要的任何约定,但我讨厌盲目地逆流而上。

【问题讨论】:

    标签: objective-c cocoa


    【解决方案1】:

    这样做实际上是有技术原因的。如果将每个shoelaceWithString:-type 方法更改为仅withString:,我们最终会得到大量具有相同名称方法和不同签名的类。这对编译器的静态类型检查起到了恶作剧的作用,并可能导致它抛出各种烦人且不必要的警告。

    还有一个 Cocoa 文化的方面,即开发人员喜欢他们的代码是自我记录的。这意味着方法名称指示它们的参数是什么以及它们返回什么。 Apple 的编码指南实际上警告了名称模糊的方法,建议在名称中添加单词以明确方法的作用。

    【讨论】:

    • 非常感谢,查克。这是非常有用的信息,感谢您的回复。
    【解决方案2】:

    因为它是一致的。

    有如下方法:

    [NSDictionary dictionary]
    [NSArray array]
    

    摆脱with 之前的所有内容显然不是这里的选择。保留这些,但缩短其他的会导致便利方法的命名不一致。

    并且便捷方法与initinitWith…方法一致。

    【讨论】:

      【解决方案3】:

      我认为这只是 cocoa 框架的“准确地说出你的意思”的一般哲学的一部分。几个选择:

      [UIView setAnimationBeginsFromCurrentState]
      [UITableView scrollToNearestSelectedRowAtScrollPosition]
      [UIApplication didRegisterForRemoteNotificationsWithDeviceToken]
      

      等等

      预计到达时间:

      为了回答具体关于构造函数的问题,我喜欢它们完成方式的一件事是,在 x-code 中很容易识别哪些方法是构造函数类型的方法。例如,您开始输入:

      [NSString string
      

      “智能感知”将方法列表缩减为以“字符串”开头的方法列表,这些方法当然都是构造函数方法(并且所有这些方法都方便地组合在一起)。同样的事情也适用于“init”约定。

      【讨论】:

      • 当您来自 C# 并获得大量代码以读取为 int a、b、c 时,witch 是一件轻而易举的事; ... :-/
      • @eric:我同意,哈哈。但是在您的示例中很容易在实现文件中阅读。但在这个“roger roger”案例中,实现会卡顿,但声明看起来很合理:具有讽刺意味的是,您最终只输入了一次声明,但您余生的实现......
      【解决方案4】:

      最终,我相信 Cocoa 框架(以及之前的 NextStep 框架)所体现的 Objective-C 哲学是明确且易于维护优先于简洁的代码。这种哲学的主要证据是 Objective-C 选择器具有命名参数(例如-[NSObject performSelector:withObject:])。

      对于+[NSString stringWithString:]等工厂方法,您必须记住,子类可能会覆盖这些类方法以返回子类(例如NSNumber等类簇)。

      因此,您最终可能会得到像 [MyPoorlyNamedSubclass stringWithString:] 这样的调用,在这种情况下,-[MyPoorlyNamedSubclass withString:] 不会明显提供有关返回对象类型的信息(回想一下,许多工厂方法返回类型 id)。另一方面,stringWithString: 清楚地表明该方法将返回一个字符串(或其子类)。

      【讨论】:

        【解决方案5】:

        他们还使用一个额外的词来判断对象是否是自动释放的。 initWithFormat 是用于非自动释放的,当它的 stringWithFormat 是自动释放的......我猜他们只是用那种方式告诉读者对象使用什么样的内存管理......

        【讨论】:

          【解决方案6】:

          如果你不喜欢它,为什么不写一堆你所有项目中包含的#define 语句?

          【讨论】:

          • 这绝对是我可以忍受的东西,但有很多次想知道。但是,是的,我确实有一些宏可以使常用的 conv-contr 更短且更易于键入...从技术上讲,这些定义不代表反模式吗?
          • 我认为这是一个糟糕的主意。即使它对您有意义,但当其他人必须维护它时,您的代码的可读性就会大大降低。
          • 这不是问题的答案。如果他问我如何使用我选择的约定,那么你的回答就可以了
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-10
          相关资源
          最近更新 更多