【问题标题】:Good practice for disambiguating argument names versus instance variable names in Objective-C在 Objective-C 中消除参数名称与实例变量名称歧义的良好做法
【发布时间】:2012-01-05 18:08:12
【问题描述】:

我在 Objective-C 中遇到了一个相当常见的场景,我将一个变量传递给一个 init 方法,然后想将它分配给一个同名的实例变量。但是,我还没有找到一种方法来确定变量范围以阐明哪个是消息参数的值,哪个是实例变量。

假设我有一些课程,如下所示:

@interface MyObject
{
    NSString *value;
}
- (id)initWithValue:(NSString *)value;
@end

在我的实现中,我希望我的 init 方法看起来像这样:

- (id)initWithValue:(NSString *)value
{
    self = [super init];
    if(self) {
        self.value = value;  // This will not work with instance variables
    }
}

我知道三种解决方案:

  1. 创建一个属性,允许调用self.value
  2. 重命名我的实例变量,如_value
  3. 重命名我的初始化参数变量,例如initValueargValue

我对这些解决方案都不满意。添加属性或者使该属性在接口上公开可用,或者,如果我使用扩展,则将其对继承者隐藏。我也不喜欢为变量使用不同的名称或使用下划线,这可能来自于使用其他语言(如 Java 和 C#)进行开发。

有没有办法从消息参数中消除实例变量的歧义?如果没有,Cocoa 中是否有关于如何解决此问题的编码指南?我喜欢在适当的时候遵循风格指南。

更新

在考虑了如何在 C 中做到这一点后,我想出了self->value 的解决方案。这可行,但它会产生一个编译器警告,即 'value' 的本地声明隐藏了实例变量。所以这也不是一个令人满意的解决方案,因为我的目标是零警告。

【问题讨论】:

    标签: iphone objective-c ios cocoa


    【解决方案1】:

    对于设置器(以及扩展初始化器),我相信约定是在参数名称前加上new

    - (void)setCrunk:(Crunk *)newCrunk;
    - (id)initWithCrunk:(Crunk *)newCrunk;
    

    总的来说,我认为我见过的最常见的形式是调用参数theCrunk,但是Apple seems to recommendaCrunk

    【讨论】:

    • 我使用crunkIn,否则您将无法获得自动完成功能。
    • @Josh Caswell,为了保持一致性,惯例是在所有情况下都使用您选择的任何前缀(new、the、a)——即使您没有分配它?也许它只是简单地传递到另一个消息中,例如到[super setCrunk:]
    • @DavidV:除非有必要用 ivar 消除歧义,否则我会说不要使用前缀,但我不能假装这是我的偏好。
    • 我喜欢aCrunk,因为它只需输入一个额外的字符。
    【解决方案2】:

    将名称更改为“inValue”不是一个好主意吗?您在这里所拥有的 - 您的“解决方案”很复杂,尤其是 Obj-C 2 的访问器等。由于 self.value 和 inValue 是不同的东西,它们需要不同的名称。

    注意,你可以使用

    -(void)method1:(NSString*)value; 
    

    在标题中

    -(void)method1:(NSString*)inValue; 
    

    在 .m 文件中。

    【讨论】:

    • 我注意到你可以在接口和实现中使用不同的参数名称。我的目标是保持一致性,以便开发人员不必考虑使用什么名称。你在接口和实现中使用了不同名称的约定吗?您的团队的效果如何?
    • @DavidV 这是一个与接口无关的问题,仅与实现有关。汤姆的观点 100% 有效。
    • @Yar,我并不是说汤姆的观点无效。我知道界面将保持一致,并且在该类中工作的开发人员将为 ivars 提供一致的命名方案。很简单,这是我最初没有考虑过的解决方案,直到我阅读了 Tom 的帖子,现在我正在考虑它。我确实认为接口的一致性高于实现的一致性,但我仍然喜欢后者。
    • @DavidV 明白了。也就是说,如果方法很短(应该如此),您可以看到开发人员为 paramIn 名称选择的约定。另一方面,接口应该完全一致
    【解决方案3】:

    如果你只使用 1,编译器会给你一个警告。

    您可以使用 1 和 2 组合:

    @synthesize value = _value;
    

    如果你想对继承者隐藏你的变量,你可以声明一个空的命名类别并在那里声明你的属性。

    对于 3,您可以使用 aValue 作为参数。

    【讨论】:

    • 某处(不记得)写到您不应该使用_ 作为前缀。只有苹果这样做。您应该将其用作后缀,这是 Google 在某处推荐的(我也不记得了)。所以value = value_...查看kevincallahan.org/software/accessorizer.html,如果您认真使用此解决方案,还可以查看 AppCode。
    • 我不同意,这只是一种风格约定。
    • 您不同意 Apple 建议不要使用下划线作为前缀?
    • 我不同意您的评论:Apple 不建议这样做。
    • 是的,建议不要在方法名称前加上下划线。变量的_ 只是风格问题。如果我@synthesize myVar = _myVar; 并且我重写了一个方法,xcode 将自动完成到- (void)setMyVar:(id)myVar;。如果与其他程序员 ivar 发生命名冲突,我很快就会收到警告。主要的是在每个项目的基础上保持一致。如果我为别人的项目工作,我会适应使用他们曾经使用过的东西来保持一致性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    • 2010-10-07
    • 2019-12-27
    • 2018-08-23
    • 2010-11-13
    相关资源
    最近更新 更多