9

Considering the java code below:

class Enclosing {
    void method(){}
    void method(String str){}

    class Inner {
        void method(){}
    }   
}

I am reading a book which tells me that Inner.method() will hide both versions of Enclosing.method(), which means it is an error if I call method(aString) somewhere in class Inner.

Why is the language designed like that?

Update:
According to the answer given by @Debosmit Ray, it is related to shadowing. I have read the docs and understood what it is.

What still confusing me is why method shadowing is based on method name not method signature?

Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
free6om
  • 438
  • 3
  • 10
  • 1
    It isn't confined to inner classes. A derived class has the same behaviour. These are just the rules of Java. C++ is the same. – user207421 Mar 19 '16 at 05:29

4 Answers4

2

Non-static nested class or inner classes are used as a way to logically group classes that are only used in one place; it makes the code more readable and promotes encapsulation.

From [docs],

If a declaration of a type (such as a member variable or a parameter name) in a particular scope (such as an inner class or a method definition) has the same name as another declaration in the enclosing scope, then the declaration shadows the declaration of the enclosing scope.

Shadowing here would mean that if you have a variable x in the outer class and another variable x in the inner class, modifying x in the inner class would not affect the x in the outer class.

I quite liked this question and the point you brought up. Does my explanantion help you understand?

Debosmit Ray
  • 5,228
  • 2
  • 27
  • 43
  • Still confusing. The docs seems to describe **variables** shadowing, does the same rule apply to **methods**? – free6om Mar 18 '16 at 07:42
  • @free6om Yep. It's exactly the same. – Debosmit Ray Mar 18 '16 at 07:49
  • OK. May be it's another question, why method shadowing is based on **method name** not **method signature**? – free6om Mar 18 '16 at 07:55
  • @free6om Yep. This would be a completely different topic. To be more particular, I would say that it is based on signatures, since if 2 methods have the same name, it's signatures would ensure uniqueness. – Debosmit Ray Mar 18 '16 at 07:58
  • @free6om It would be nice, if you could accept/upvote an answer if your issue is resolved. From [here](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work), "Accepting an answer is important as it both rewards posters for solving your problem and informs others that your issue is resolved." – Debosmit Ray Mar 18 '16 at 08:00
1

Had you found the correct tag for your question, you would have understood the concept better already! Take look at the tag info for shadowing right on SO.

In computer programming, shadowing occurs when a variable declared within a certain scope (decision block, method or inner class) has the same name as a variable declared in an outer scope. This can lead to confusion, as it may be unclear which variable subsequent uses of the shadowed variable name refer to, which depends on the name resolution rules of the language.

One of the first languages to introduce variable shadowing was ALGOL, which first introduced blocks to establish scopes. It was also permitted by many of the derivative programming languages including C++ and Java.

The C# language breaks this tradition, allowing variable shadowing between an inner and an outer class, and between a method and its containing class, but not between an if-block and its containing method, or between case statements in a switch block.

Wikipedia link (doesn't provide much though)


Why is the language designed like that?

Let me give you a real world analogy to might help you understand.

Think of a building (1) that has a button named Turn on lights (3). When you press that button, it turns on all the lights in the building. Now think of a cubicle (2) inside that building. There is a small lamp in that cubicle, and a similar button named Turn on lights. Now when you press that button, what do you want it to do -- turn on all the lights of the building, or just the lamp in the cubicle? Probably the latter. Though both the buttons have the same name (4), they behave differently depending on their place (5).

Now apply this analogy to OOP. Look at the words in italics one more time, and match up!

  1. building --> Enclosing class
  2. cubicle --> Inner class
  3. Turn on lights --> Method
  4. name --> Method name/signature
  5. place --> Scope

Please note that the analogy doesn't take into consideration many other concepts of OOP, but I think it might help you understand the why part of your question.


Reply to Update:

What still confusing me is why method shadowing is based on method name not method signature?

Your question doesn't seem to be a valid one. You will understand this shortly.

You said shadowing is not based on method signature. If what you mean by this is: "if inner class method has same signature as enclosing class method, then shadowing doesn't take place", then you are wrong. Try it out by making a another method inside the inner class like void method(String str) and then calling that method inside the inner class. You will see that it is obviously shadowed.

And the reason why you got an error when you invoked method(aString) inside the inner class is completely something else-- the method method(String str) doesn't even exist inside the inner class scope.

Feel free if you need further clarification.

Community
  • 1
  • 1
Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
  • I read the tag info for shadowing, It all talks about **variables**, does the same rule apply to **methods**? – free6om Mar 18 '16 at 07:27
  • @free6om That's right. Shadowing applies to methods too. Take a look at the updated answer. I believe it will make the thing clearer to you! If it does, you may want to accept this answer as well. :) – Sнаđошƒаӽ Mar 18 '16 at 11:22
  • About the method shadowing, what I mean is if we call `method(aString)` in other method of class Inner, saying `caller()`, the compiler will complain. It seems that method `method()` in class Inner shadows both `method()` and `method(String str)` in class Enclosing, even if method `method(String str)` has different signature. – free6om Mar 18 '16 at 13:30
  • @free6om I explained that part already. Your not being able to invoke `method(aString)` from `caller()` in class `Inner` doesn't mean that `method()` in `Inner` class has shadowed both `method()` and `method(String str)` in Enclosing class, but rather, you are not able invoke `method(aString)` from within class `Inner` because there is no method in the scope of `Inner` with the signature `method(String str)`. Take a look at the error message you get when you try to call `method(aString)` from within `Inner`. You will get [this error](http://goo.gl/YCHx5a) – Sнаđошƒаӽ Mar 18 '16 at 15:20
  • @free6om did my answer help you? If you need further clarification, we can continue in a chat room. And if it did, consider marking this effortful answer as accepted to give some credits to its writer! :) – Sнаđошƒаӽ Mar 19 '16 at 03:58
  • Sorry for the late credits. Your answer is very convincing, thank you! – free6om Mar 19 '16 at 08:49
1

This is called shadowing.

According to JLS 6.4.1

Some declarations may be shadowed in part of their scope by another declaration of the same name, in which case a simple name cannot be used to refer to the declared entity.

It's convenient to have shadowing in programming language. For example, in constructors, you can have both parameters and class field variables the same name, and use this to distinguish them.

class Person {
    private String name;
    Person (String name) {
        this.name = name;
    }
}

In some other languages, variables may be shadowed by code blocks, for example, in C++ you can write code like:

// C++ code:
int i = 10;

for(int i = 0; i != 5; ++i) {
    // use i from 0 to 4 here
}

for(int i = 100; i > 0; --i) {
    // use i from 100 to 1 here
}

// the first i is still 10 and can be used here

The variable i inside the loop is different from the outside i.

Why is the language designed like that?

As you can see in the constructor example, sometimes variables may really mean the same thing. Shadowing makes you can use the same names without creating a new name, which is kind of bothering because naming a variable is not quiet simple.

And in the loop sample, which is not supported in Java but is a great sample to show the advantage of shadowing, sometimes in code block you may declared some temporary variables without modifying other variables outside the block.


Why method shadowing is based on method name not method signature?

In JLS 15.12, there's a explanation about method invocation.

You can see that in step 1, compiler will search for the scope that can call this method. In the end, it found Enclosing.Inner.

And at step 2, compiler will check signature of the methods.

Therefore, compiler will take Enclosing.Inner.method() as the only method that is available to call. That's why you can't call Enclosing.method(String str) directly, even though they have different method signature.

If you want to call Enclosing.method(String str) inside the Inner class, you can do:

class Inner {
    void method(){
        Enclosing.this.method("test");
    }
}
Nier
  • 638
  • 7
  • 15
  • The `for` loop will never compile. You have initialized 2 variable with the same name, within the same scope. Moreover, that doesn't explain forwarding either. – Debosmit Ray Mar 18 '16 at 21:25
  • @DebosmitRay That for loop is compiled in C++, which is mentioned in my answer. And I don't get it what is not explained in my answer? Please tell my that I can improve my answer, thanks. – Nier Mar 19 '16 at 01:53
  • I missed that part. It would be great if you could put it in bold, since the question is about java, not cpp. – Debosmit Ray Mar 19 '16 at 03:31
  • @DebosmitRay I modified my answer. Thanks for the suggestions. – Nier Mar 19 '16 at 03:54
  • That's the only answer that *actually* answers the question – Vasily Liaskovsky Mar 19 '16 at 14:42
0

Because in that Scope, Method, Variables and constants make shadow over global method and variables...

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
  • Thank you for the quick response, I don't seem to understand the meaning of **make shadow**. Any more details? – free6om Mar 18 '16 at 06:42