16

The case of shadowing class variables is common in in Java. Eclipse will happily generate this code:

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;
    }
}

Is variable shadowing ever ok?

I am considering the implementation of a coding rule saying that "shadowing will not be allowed." In the simple case above it is clear enough what is going on. Add in a little more code that does something and you run the risk of missing "this" and introducing a bug.

What is the general consensus? Ban shadowing, allow it sometimes, or let it roll?

Chuck
  • 998
  • 8
  • 17
  • 30
  • Unless I'm mistaken, this isn't "shadowing" at all, it's just variable "scoping". The use of `this.` is just an explicit way to reference the variable that is currently out of scope. Am I mistaken? – Enigmativity Aug 12 '11 at 05:12

10 Answers10

23

I actually prefer the guideline "Shadowing is only allowed in constructors and setters". Everything else is not allowed.
Saves you the trouble of naming constructor arguments aValue and aTest just to avoid shadowing.

If you're using eclipse, its warnings settings can be set exactly to that option BTW.

abyx
  • 69,862
  • 18
  • 95
  • 117
  • Eclipse can actually be configured to give you an error/warning in all cases except constructors. Unfortunately, it doesn't automatically know what is a getter or setter. – Tyler Feb 16 '10 at 07:21
  • 1
    @abyx: That seems a reasonable compromise. @OP: In general, this kind of shadowing is a bad idea and a maintenance issue (a lot of Java programmers even now leave `this.` off when they can, creating the ambiguity and leading to subtle bugs). But an exception for constructors, getters, and setters (provided they're *simple*, as they should be) seems reasonable. – T.J. Crowder Feb 16 '10 at 07:26
  • @Joachim: I can't believe I didn't catch that. In mitigation, I hadn't had my coffee yet. – T.J. Crowder Feb 16 '10 at 07:33
  • 2
    @MatrixFrog - I just downloaded eclipse galileo. Preferences->Java->Compiler->Errors/Warnings->Name shadowing->Local variable decleration hides...->Uncheck "include constructor and setter method parameters" – abyx Feb 16 '10 at 07:33
  • my take is "shadowing this with parameters is allowed only when they are the same in the current context". the same goes for naming variables like method parameters - that way 'line' in my local context is _the same_ 'line' that a method expects, and so on. – Asaf Feb 16 '10 at 08:09
  • @abyx Okay, I guess it can figure out which methods are setters. Cool. – Tyler Feb 16 '10 at 08:26
  • @Joachim Sauer. If you want to return a copy of the property (.equal but not ==) why not use shadowing? `int[] getArr(){int[] arr=new int[this.arr.length]; System.arraycopy(...); return arr;}` – KitsuneYMG Feb 18 '10 at 21:45
3

I feel safe with variable shadowing when using IDEs such as Eclipse and IntelliJ IDEA which highlight fields in different colors than the local variables and also provide helpful warnings on local variable mis-uses.

Amir Moghimi
  • 1,391
  • 1
  • 11
  • 19
3

Shadowing can be useful in simple code such as constructors getters setters and anything of the sort.

However the use of descriptive variables is really important so instead of using this

this.name = name; try this this.name = newName;

Also, if you make a habit of including this. in your code it becomes second nature and helps quite a bit with readability

CheesePls
  • 887
  • 1
  • 6
  • 17
  • I like the "new" prefix. Why haven't I seen more use of that?! – T.J. Crowder Feb 16 '10 at 07:36
  • Because using 'new' isn't right in a constructor, only in a setter. – abyx Feb 16 '10 at 07:42
  • @abyx: Probably, I was thinking about that too. But I can get past it. :-) – T.J. Crowder Feb 16 '10 at 07:58
  • a lot of people avoid the new- prefix because new is a reserved word and if you leave a space between new and your word it creates an object accidentally. I still like the name because I don't really have that issue. – CheesePls Feb 16 '10 at 11:51
2

A good IDE like Eclipse shows you, in different colours and/or fonts, the attributes and the method variables of your class. Becaus of that variable shadowing is OK.

Tim
  • 2,831
  • 1
  • 25
  • 37
  • 1
    And the people doing maintenance after you are going to be using such an IDE? You're sure? Their colors are going to be set up to be clearly distinct? – T.J. Crowder Feb 16 '10 at 07:34
  • @Abyx: Perhaps they don't see it as regression. Perhaps they find the colors distracting. Or they're vision-impaired and only simple black and white work. Or...or...or... Tools are great, and we should use tools to help us, but this seems like asking for trouble. – T.J. Crowder Feb 16 '10 at 07:56
  • @T.J. - One needs tests any way, and those will make sure people don't mix members and variables up. – abyx Feb 16 '10 at 10:45
  • @ T.J. Crowder (first comment): I'm not sure. But everyone must know what he do! You can work with notepad if you want! And if you have no test coverage it is your own fault I think. – Tim Feb 16 '10 at 18:46
1

I actually set up my install of Eclipse to issue warnings for every under-qualified variable. This ensures I never forget to prefix implementation variables with this.. This has effectively preemptively solved any problem that might arise from shadowing.

You can do this by way of Preferences > Java > Compiler > Errors/Warnings >> Code Style > Unqualified access to instance field.

amphetamachine
  • 27,620
  • 12
  • 60
  • 72
  • 1
    That's a very good thing to do, but it only addresses *your* problem with shadowing. People doing maintenance after you may not have the same settings enabled, or may be using an IDE that doesn't support doing it, or may need to be doing an emergency edit in some minimalist editor. – T.J. Crowder Feb 16 '10 at 07:35
  • @T.J. Crowder - But Java isn't what I would call a minimalist language. :-) Unified? yes. Terse? hell no. It's almost impossible (for me at least) to develop unfrustratingly in a regular text editor. – amphetamachine Apr 30 '10 at 13:40
1

I do "this" shadowing all the time. In complex places, it's useful to use an explicit this even if it doesn't shadow anything. It makes it easier to distinguish between local and class variables, from the human viewpoint (although, then it becomes an issue that you must be consistent; using this a little bit here and there but not everywhere is confusing).

In Python, you don't even have the choice: plain x is always local. Class members are self.x.

Joonas Pulakka
  • 36,252
  • 29
  • 106
  • 169
0

Shadowing is always bad. Name your variables after their scope (not type), and you'll save yourself the hassle.

Rick
  • 3,298
  • 3
  • 29
  • 47
0

Well, I dont see any problem with this code. Its good that IDE is helping you to reduce the amount of code that you have to write.

Sahil
  • 121
  • 9
0

A valid case is that it provides a telling signature, so those maintaining the app Can easily see which fields are passed in the Call.

The Builder pattern is, however a better solution for maintainability.

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
0

The main justification for style rules is to make code readable, both to the original author and to others who need to maintain it. In this context, readability is about being able to easily understand what the code actually does, both at the mechanistic level and at the deeper semantic level.

In general, (apart from constructors and setters) variable hiding tends to be considered bad style because it causes the casual reader to mistake uses of locals for uses of members, and vice versa. (An IDE that highlights member names tends to mitigate this, but it is still easy to miss the distinction.) And (apart from constructors and setters) there is generally a clear semantic distinction between the local and the member with the same name, and this is best reflected by using different names.

Setters and constructors are a bit different in each of the respects above. Since setters (in particular) and constructors are simple and stylized, the hiding of the form shown is unlikely to cause a casual reader and confusion. Indeed, I would argue using only one identifier for what is essentially the same information may actually make the code easier to read.

On this basis, I would say that hiding in constructors and setters is perfectly acceptable. A style rule that rigidly insists that you should avoid hiding in this context is (IMO) pedantic and maybe counter-productive. And it is certainly out of step with what most Java coders would consider to be normal practice.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216