“this”阴影是个好主意吗?

16

在Java中,遮蔽类变量的情况很常见。Eclipse可以轻松生成以下代码:

public class TestClass {
    private int value;
    private String test;
    public TestClass(int value, String test) {
        super();
        this.value = value;
        this.test = test;
    }
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
    public String getTest() {
        return test;
    }
    public void setTest(String test) {
        this.test = test;
    }
}

变量遮蔽有什么好处吗?

我正在考虑实施一项编码规则,即“不允许遮蔽”。在上面的简单情况下,很清楚正在发生什么。增加一些执行某些操作的代码,您可能会错过“this”并引入错误。

普遍意见是什么?禁止遮蔽、有时允许或任由其自由发展?


除非我错了,这根本不是“阴影”,只是变量“作用域”。使用this.只是一种明确引用当前超出范围的变量的方式。我错了吗? - Enigmativity
10个回答

23

我实际上更喜欢指南“只有在构造函数和设置器中允许影子变量”。其他情况都是不允许的。
这样可以避免为了避免变量名重复而命名构造函数参数aValueaTest之类的名称。

如果你使用eclipse,它的警告设置可以精确地设置到该选项。


Eclipse实际上可以配置为在除构造函数之外的所有情况下都给出错误/警告。不幸的是,它无法自动识别getter或setter。 - Tyler
1
@abyx:这似乎是一个合理的妥协。@OP:一般来说,这种遮蔽是个坏主意,并且会引起维护问题(现在很多Java程序员甚至在可以的情况下省略this.,导致模糊并引发微妙的错误)。但是对于构造函数、getter和setter(只要它们是简单的,就像它们应该的那样),做出例外似乎是合理的。 - T.J. Crowder
@Joachim:我简直不敢相信我没发现那个问题。为了辩解,我还没有喝咖啡。 - T.J. Crowder
2
@MatrixFrog - 我刚刚下载了Eclipse Galileo。 首选项->Java->编译器->错误/警告->名称遮蔽->本地变量声明隐藏...->取消选中“包括构造函数和设置器方法参数”。 - abyx
@abyx 好的,我猜它可以找出哪些方法是设置器。很酷。 - Tyler
显示剩余2条评论

3

当使用Eclipse和IntelliJ IDEA等IDE时,我觉得变量影子是安全的,因为它们以不同于本地变量的颜色突出显示字段,并在本地变量误用时提供有用的警告。


3

Shadowing在简单的代码中非常有用,例如构造函数、getter、setter等。

然而,使用描述性变量真的很重要,因此不要使用这个:

this.name = name; 尝试使用这个 this.name = newName;

另外,如果你习惯在代码中包含this.,它会变成一种习惯,并且对可读性有很大帮助。


我喜欢“new”前缀。为什么我没有看到更多的使用呢?! - T.J. Crowder
因为在构造函数中使用“new”是不正确的,只能在setter中使用。 - abyx
@abyx:可能吧,我也在考虑这个问题。但是我可以克服它。 :-) - T.J. Crowder
很多人避免使用new-前缀,因为new是一个保留字,如果在new和你的单词之间留下空格,会意外地创建一个对象。我仍然喜欢这个名称,因为我并没有遇到这个问题。 - CheesePls

2
一个好的IDE,比如Eclipse,会用不同的颜色和/或字体来显示您的类的属性和方法变量。因此,变量遮蔽是可以的。

1
维护你代码的人会使用这样的IDE吗?你确定吗?他们的颜色设置会清晰可辨吗? - T.J. Crowder
@Abyx:也许他们并不认为这是回归问题。也许他们觉得颜色会分散注意力。或者他们视力有障碍,只能使用简单的黑白颜色。或者...或者...或者... 工具很好,我们应该利用工具来帮助我们,但这似乎是在自找麻烦。 - T.J. Crowder
@T.J. - 无论如何都需要测试,这些测试可以确保人们不会混淆成员和变量。 - abyx
@ T.J. Crowder(第一条评论):我不确定。但每个人都必须知道他在做什么!如果你想的话,可以使用记事本工作!而且,如果你没有测试覆盖率,那就是你自己的问题了。 - Tim

1

实际上,我设置了我的Eclipse安装以发出每个不合格变量的警告。这确保我永远不会忘记在实现变量前加上“this.”。这有效地预先解决了任何可能由阴影效应引起的问题。

您可以通过首选项> Java>编译器>错误/警告>>代码风格>未限定访问实例字段来实现此操作。


1
这是一个非常好的做法,但它只解决了在阴影处理方面的问题。在你之后进行维护的人可能没有启用相同的设置,或者可能正在使用不支持此操作的IDE,或者可能需要在某些极简编辑器中进行紧急编辑。 - T.J. Crowder
@T.J. Crowder - 但是我不认为Java是一种极简主义语言。统一?是的。简洁?绝对不是。在常规文本编辑器中开发几乎是不可能的(至少对我来说),会让人感到沮丧。 - amphetamachine

1
我一直都在做“这个”的阴影处理。在复杂的地方,即使没有遮盖,使用显式的this是很有用的。从人类的角度来看,这使得区分局部变量和类变量更容易(虽然,这样就成为一个问题,你必须保持一致;这里有点使用this而不是到处都使用是令人困惑的)。
在Python中,你甚至没有选择:普通的x总是局部的。类成员是self.x

0

嗯,我认为这段代码没有问题。IDE帮助你减少了需要编写的代码量,这是很好的。


0
一个有效的情况是它提供了一个有意义的签名,这样维护应用程序的人员可以轻松地看到在调用中传递了哪些字段。
然而,建造者模式是更好的可维护性解决方案。

0

编程风格规则的主要理由是使代码易读,无论对于原始作者还是其他需要维护代码的人来说都是如此。在这个上下文中,易读性涉及到在机械层面和更深层语义层面上能够轻松理解代码实际执行的内容。

一般而言,(除了构造函数和设置器)变量隐藏往往被认为是不好的风格,因为它会导致初读者将局部变量误认为成员变量的使用,反之亦然。(突出显示成员变量名字的集成开发环境有助于缓解这个问题,但仍然很容易忽略这种区别。)另外,(除了构造函数和设置器)局部变量与同名成员变量一般会存在明确的语义区别,最好使用不同的名称来体现。

设置器和构造函数在上述各个方面有些许不同。由于设置器(尤其是)和构造函数具有简单且格式化的特点,所以隐藏所展示的形式不太可能引起初读者的困惑。实际上,我认为只使用一个标识符来表示本质上相同的信息可能会使代码更易读。

基于这一点,我认为在构造函数和设置方法中隐藏变量是完全可以接受的。我认为那些坚持严格避免在这种情况下隐藏变量的风格规则有点迂腐,也可能会适得其反。而且它显然与大多数Java程序员认为是正常做法的步调不一致。

0

变量名遮蔽总是不好的。按照作用域(而非类型)命名变量,可以避免麻烦。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接