我在C ++和Java中的一个令人讨厌的(?)编程习惯总是在调用或访问this
成员之前。例如:this.process(this.event)
。
我的一些学生评论了这一点,我想知道我是否在教习坏习惯。
我的理由是:
显然,这对编译的程序没有任何影响,只是可读性。那么我是否会使它具有或多或少的可读性?
注意:因为确实没有正确答案,我把它变成了CW。
答案 0 :(得分:44)
我认为它的可读性较差,特别是在字段的突出显示与局部变量不同的环境中。我想要看到“这个”的唯一时间是需要时,例如:
this.fieldName = fieldName
分配字段时。
那就是说,如果你因某种原因需要某种方法来区分字段,我更喜欢“this.fieldName”到其他约定,比如“m_fieldName”或“_fieldName”
答案 1 :(得分:17)
这是一个非常主观的事情。 Microsoft StyleCop有一条规则需要 this。限定符(尽管它与C#相关)。有些人使用下划线,有些人使用古怪的匈牙利符号。我个人对这个。的成员进行了限定,即使它没有明确要求避免混淆,因为有些情况下它可以使一个人的代码更具可读性。
您可能还想查看此问题:
What kind of prefix do you use for member variables?
答案 2 :(得分:15)
在我加入现任雇主之前,我从未见过这种风格。我第一次看到它时,我认为“这个白痴根本不知道,Java / OO语言通常不是他的强项”,但事实证明,这是一个经常发生的痛苦,并且是几个项目的强制性风格,尽管
这些项目也是如此if (0 == someValue)
{
....
}
做条件的方法,即将常数放在测试中,这样你就不会冒写作的风险
if (someValue = 0)
意外 - 忽略编译器警告的C编码员的常见问题。事实上,在Java中,上面只是无效的代码,并且会被编译器抛弃,所以他们实际上使他们的代码不那么直观,没有任何好处。
因此,对于我来说,对于我来说,远远没有表现出“作者正在用专门的思考过程进行编码”,这些事情让我觉得更有可能来自那种只是坚持其他人告诉他们的规则而没有质疑的人他们或首先了解规则的原因(因此规则不适用)。我听到的原因主要归结为“这是最佳实践”,通常引用Josh Bloch的 Effective Java ,这在这里有很大影响。事实上,Bloch甚至没有使用它,即使我认为他可能应该提供可读性!再一次,被告知这样做并且不知道为什么的人似乎做了更多的事情!
就个人而言,我更倾向于同意Bruce Eckel在Thinking in Java(第3版和第4版)中所说的内容:
'有些人会痴迷地将这个放在每个方法调用和字段引用之前,认为它使它“更清晰,更明确”。不要这样做。我们使用高级语言是有原因的:他们为我们做事。如果你在没有必要的时候加上这个,你会混淆并惹恼所有阅读你代码的人,因为他们读过的所有其他代码都不会使用到处都是这个。人们希望此仅在必要时使用。遵循一致且直接的编码风格可以节省时间和金钱。'
脚注,第169页,Java思考,第4版
相当。少即是多,人。
答案 3 :(得分:10)
3个原因(Nomex适合开启)
1)标准化
2)可读性
3)IDE
1)biggie 不属于Sun Java代码样式。
(不需要Java的任何其他样式。)
所以不要这样做(用Java。)
这是蓝领Java事物的一部分:到处都是一样的。
2)可读性
如果你想要这个,你可以把它放在每个this.the this.word;你真的这么认为它改善了这个可读性吗?
如果一个类中有太多的方法或变量让你知道它是否是成员......重构。
您只有拥有成员变量,并且您没有Java中的全局变量或函数。 (在其他语言中,你可以有指针,数组溢出,未经检查的异常和全局变量;享受。)
如果你想告诉方法是否在你的类父类中... 记得把@Override放在声明上,让编译器告诉你是否没有正确覆盖。如果你希望调用父方法,则super.xxxx()是Java中的标准样式,否则将其遗漏。
3)IDE 任何人在没有理解语言的IDE的情况下编写代码并在侧边栏上给出一个大纲,都可以在他们自己的镍上完成。意识到如果它不是语言敏感的话,你就会被困在1950年代。没有GUI:被困在50年代。
任何体面的IDE或编辑器都会告诉您函数/变量的来源。即使是最初的VI(<64kb)也可以用CTags做到这一点。使用蹩脚的工具只有没有借口。好的是免费赠送的!
答案 4 :(得分:9)
有时我喜欢写这样的课程:
class SomeClass{
int x;
int y;
SomeClass(int x, int y){
this.x = x
this.y = y
}
}
这样可以更容易地判断哪个参数设置了哪个成员。
答案 5 :(得分:6)
我认为更具可读性。我出于同样的原因,按照你的方式做到了。
答案 6 :(得分:5)
我发现少即是多。你的代码中有更多不必要的冗长垃圾,人们维护它的问题就越多。也就是说,具有清晰一致的行为也很重要。
答案 7 :(得分:4)
在我看来,你让它更具可读性。它让潜在的未来故障排除者知道您正在调用的功能是什么。
其次,使用具有完全相同名称的全局函数或从某个命名空间中“使用”变为冲突的函数并非不可能。因此,如果存在冲突,原始代码作者将确定他们正在调用哪个函数。
当然,如果存在名称空间冲突,其他一些清洁编码规则正在被打破,但没有人是完美的。因此,我认为任何不妨碍生产力的规则都有可能减少错误(无论多么微不足道),并且可以使未来的故障排除目标变得更容易,这是一个很好的规则。
答案 8 :(得分:3)
有一个很好的技术理由倾向于使用或避免this
- 两者并不总是等同。
请考虑以下代码:
int f();
template <typename T>
struct A
{
int f();
};
template <typename T>
struct B : A<T>
{
int g()
{
return f();
return this->f();
}
};
现在,f()
中有两个B<T>::g()
来电。人们会期望它呼叫A<T>::f()
,但只有第二个呼叫::f()
。第一个会拨打A<T>
。这背后的原因是因为T
依赖于this
,所以查找通常不会找到它。 B<T>
作为指向T
的指针,也依赖于B<T>
,因此如果您使用它,查找将会延迟到实例化{{1}}之后。< / p>
请注意,某些编译器(特别是MSVC)可能不会出现这种行为,这些编译器没有实现两阶段名称查找,但仍然是正确的行为。
答案 9 :(得分:2)
Python人员一直这样做,几乎所有人都喜欢它。他们把它拼写为“自我”而不是“这个”。有很多方法可以明确表达“自我”,但共识是明确的“自我”对于理解类方法至关重要。
答案 10 :(得分:2)
我使用this
至少有两个原因:
我喜欢在C ++,C,Java,C#或JavaScript编码时拥有一致的代码样式。我保持自己使用相同的编码风格,主要是受到java的启发,但受到其他语言的启发。
我也希望用一种语言保持代码内部的连贯性。我使用typename
作为模板类型参数,而不是class
,我从不使用两者来玩混音器。这意味着我讨厌必须在某一时刻添加this
,但完全避免它。
我的代码相当冗长。我的方法名称可能很长(或没有)。但他们总是使用全名,而不是压缩名称(即getNumber()
,而不是getNbr()
)。
从技术角度来看,这些原因并不是很好,但是,这仍然是我的编码方式,即使它们没有(很多)好,也没有(很多)邪恶。事实上,在我所处理的代码库中,其他人编写了足够多的历史反模式,让他们质疑我的编码风格。
当他们学习写“异常”或“课堂”时,我会再次考虑这一切......
虽然我很欣赏编译器的工作,但是我有一些含糊不清的想法让人不明白。
例如,我(几乎)从不使用using namespace MyNamespace
。我要么使用完整的命名空间,要么使用三个字母的别名。我不喜欢含糊不清,当编译器突然告诉我“打印”功能碰撞在一起时,我不喜欢它。
这就是我通过全局命名空间为Win32函数添加前缀的原因,即始终写::GetLastError()
而不是GetLastError()
。
这与this
的方式相同。当我使用this
时,我有意识地限制编译器在没有找到真实符号的情况下搜索替代符号的自由。这意味着方法,以及成员变量。
这可能显然可以用作反对方法重载的参数。但这只会是显而易见的。如果我编写重载方法,我希望编译器在编译时解决歧义。如果不写this
关键字,那不是因为我想编译器使用另一个符号而不是我想到的符号(比如函数而不是方法,或者其他)。
总而言之,这个问题主要是风格,并且有真正的技术原因。我不想让没有写this
的人死亡。
至于布鲁斯·埃克尔(Bruce Eckel)从他的“Thinking Java”中引用的内容......我对他在书中所做的偏见的Java / C ++比较(并且没有与C#进行比较,奇怪的是)给我留下了深刻的印象,所以他的个人关于this
的观点,在脚注中完成......好吧......
答案 11 :(得分:2)
我必须加入'包括这个'营地;我不是一贯地做到这一点,但从维护的角度来看,好处是显而易见的。如果维护者由于某种原因没有使用IDE,因此没有专门突出显示的成员字段和方法,那么他们就会陷入滚动痛苦的世界。
答案 12 :(得分:1)
“可读性”
我发现在不使用IDE(小型快速程序)时特别使用“this”
我的类足够大,可以将一些方法委托给一个新类,将“this”替换为“otherRef”,使用最简单的文本编辑器非常容易。
即
//Before
this.calculateMass();
this.perfornmDengerAction();
this.var = ...
this.other = ...
“重构”之后
// after
this.calculateMass();
riskDouble.calculateMass();
riskDouble.setVar(...);
this.other = ...
当我使用IDE时,我通常不会使用它。但我认为它比你使用这种方法更能让你处于一种OO方式。
class Employee {
void someMethod(){
// "this" shows somethings odd here.
this.openConnectino() ; // uh? Why an employee has a connection???
// After refactor, time to delegate.
this.database.connect(); // mmhh an employee might have a DB.. well..
}
... etc....
}
最重要的是,如果开发团队决定是否使用它,那么该决定将受到尊重。
答案 13 :(得分:1)
我认为最重要的是一致性。有合理的论据支持和反对,因此在考虑采用哪种方法时,这主要是一种品味问题。
答案 14 :(得分:1)
根本不是一个坏习惯。我自己不这样做,但当我注意到其他人在代码审查中这样做时,它总是一个加号。这是质量和可读性的标志,表明作者正在编写一个专门的思考过程,而不仅仅是黑客攻击。
答案 15 :(得分:0)
如果您不需要在成员变量前面添加 this。,那么checkstyle等静态分析工具在检测成员变量隐藏字段的情况下非常有用。通过删除这些情况,您可以首先删除使用它的需要。话虽如此,我更喜欢在构造函数和setter的情况下忽略这些警告,而不是必须为方法参数提出新的名称:)。
关于静态变量,我发现大多数不错的IDE会突出显示这些,以便您可以区分它们。使用静态常量之类的命名约定也是值得的。静态分析工具可以通过强制执行命名约定来提供帮助。
我发现静态方法很少有任何混淆,因为方法签名通常不同,足以使任何进一步的区分变得不必要。
答案 16 :(得分:0)
我更喜欢上面描述的本地分配模式,但不喜欢本地方法调用。我同意“一致性是最重要的方面”的情绪。我发现这个东西更具可读性,但我发现一致的编码更具可读性。
public void setFoo(String foo) {
this.foo = foo; //member assignment
}
public doSomething() {
doThat(); //member method
}
我有同事喜欢:
public void setFoo(String foo) {
_foo = foo;
}
答案 17 :(得分:0)
我以前经常使用这个......然后一位同事向我指出,一般来说我们会努力减少不必要的代码,所以这条规则不适用于此吗?
答案 18 :(得分:0)
从.Net的角度来看,我使用的一些代码分析工具看到了“this”,并立即得出结论,该方法不能是静态的。它可能是用Java测试的东西,但如果它在那里做同样的事情,你可能会缺少一些性能增强。
答案 19 :(得分:0)
不太可读,除非您的学生仍然像这里的学生一样在绿屏终端上......精英们有语法高手。
我刚刚听到一个谣言,他们也有重构工具,这意味着你不需要“这个”。搜索和替换,他们可以通过一个按键删除那些讨厌的冗余。显然,这些工具甚至可以拆分方法,因此它们很好,很短,就像它们本来应该开始的那样,大部分时间都是如此,然后很明显甚至对于绿色筛选器而言,这些都是领域。