Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Inner Class method acess  RSS feed

 
Mark Griffin
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have this test program for inner classes. The IDE I'm using says that the sayHello call in the foo method is a compile error because it can access both implementations. I think this is a bug in the IDE and that the only way to access the sayHello method in InnerClassTest is to use InnerClassTest.this.sayHello().

Question: Is the IDE right or am I right?

Thanks!



[Edited to use UBB Code tags to make reading code easier - GB]
[ October 01, 2004: Message edited by: Gregg Bolinger ]
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What happens when you compile it from the command line? Do you get a similar message?
 
Gregg Bolinger
Ranch Hand
Posts: 15304
6
Chrome IntelliJ IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Compiling from the Command Line (which you can do too you know) works just fine.
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When I use BlueJ the two classes compile without error, and running the program produces:

Running


(Sorry pasted too much last time)
[ October 01, 2004: Message edited by: Barry Gaunt ]
 
Mark Griffin
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yep, compiling from the command line works

I changed things around a little bit. If I run it with the BaseClass sayHello private I get:

InnerClassTest says Hello.
InnerClassTest says Hello.

If I use the default acess (remove the private) on the BaseClass sayHello method and run it I get:
BaseClass says Hello.
InnerClassTest says Hello.

My conclusion is that it finds the method in the base class first then the private method in the outer class. Is that right?




 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hang on, this thing's changing under our feet!

What of these two programs are we talking about now?
[ October 01, 2004: Message edited by: Barry Gaunt ]
 
Mark Griffin
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, sorry - I am all settled down now. The last and final test program shows different output when the sayHello method in BaseClass has private or default access. When it is private the program displays

InnerClassTest says Hello.
InnerClassTest says Hello.

When it is default the program displays:
BaseClass says Hello.
InnerClassTest says Hello.

I did not expect the call to sayHello to find the sayHello implementation in the outer class without the syntax InnerClassTest.this.sayHello().

And if I'm wrong about that then I did not expect it to silently prefer the implementation in BaseClass and not first report the method name conflict.


Thanks for your time!
-Mark
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When the sayHello() in BaseClass is private then the anonymous inner class which is a subclass of BaseClass cannot access the sayHello() in BaseClass, so it's got to be the one in the InnerClassTest class. So sayHello() is the same as InnerClassTest.this.sayHello() in this case.

When the sayHello() in BaseClass is not private then the anonymous inner class which is a subclass of BaseClass can access the sayHello() in BaseClass. So sayHello() is super.sayHello() in this case. The sayHello() in InnerClassTest is also accessible. The standard compiler is choosing the BaseClass implementation. The IDE's compiler is saying "I cannot decide so make it explicit please".

That's my analysis anyway.
 
Mark Griffin
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, I think I have it straight, thank you very much. It is hard for me to write concisly about this with all inner/outer/base class lingo but I'll give it a shot:

Private members of the enclosing class are accessible from the inner class. So, the inner class can call the InnerClassTest implementaion of sayHello.

If the base class that the inner class extends has a sayHello method then it is prefered over a method of the same name in the outer class. That allows future programmers to extend the outer class and create a method that duplicates a method name in the base class of an inner class. That is to say, the developer that extends InnerClassTest doesn't have to worry about duplicating method names that are in classes extended by inner classes in InnerClassTest.

So, to answer my original question: I think the IDE got a little anxious on me when it flagged that as an error. Base class implementation are prefered in this situation.
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Now you know why inner classes are not used to their full potential in practise. When possible use plain vanilla top-level classes in your design, then people can clue in to what your doing.
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By the way Mark, welcome to Java Ranch! Don't hesitate to post again sometime, we got Intermediate and Advanced Java In General forums too
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The Eclipse 3.0.1 IDE compiles this stuff without errors. It also has its own compiler.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Mark Griffin:

So, to answer my original question: I think the IDE got a little anxious on me when it flagged that as an error. Base class implementation are prefered in this situation.


Looks that way, yes. And I'd actually prefer the way of your IDE. Just imagine you are calling a method on the outer class, and later someone implements a similar method in the base class of the inner class. Suddenly you are calling a totally different method and might not even notice!

BTW, what IDE are you using?
 
Chris Staten
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, help me out a bit on this one. I see two classes in one source (.java) file. However I don't see a class inside a class such as:


I thought that by definition an inner class was nested inside the curly braces of its outer class. Of course I ran the code Mark posted and tried to figure it out that way, but I wasn't able to :\

Also, why is that semicolon on line 9 of the original version of his code (line 11 in the updated version) there?

Heck, while I'm at it I'll ask why can't I compile the code when I put in the following: System.out.println("testing"); right after his fifth line of code - "BaseClass b = new BaseClass() {"? The compiler error says "(identifier) expected".
[ October 01, 2004: Message edited by: Chris Staten ]
 
Mark Griffin
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The code was orignigally developed with IntelliJ Idea 4.5. That IDE correctly highlights the method in the outer class as "not being used" when the inner class finds the method in the base class. When the method in the base class is marked private IntelliJ correctly marks the method in the outer class as "in use".

Another developer pulled the code into IBM's WebSphere Device Developer version 5.6 and it marked the inner class method call as an error saying that there were two methods with that name in the scope. It found the one in the outer class and the one in the base class. I'd say the IDE should mark that as a warning, not a compile error, because the code will compile correctly. The base class method is used in this case.

Looks like there are scenarios where someone can innocently add a method and all of a sudden old code breaks. For example: A method is added to the base class of the inner class. The method has the same name as a method in the outer class containing an annonymous inner class instance of the base class. The author of the outer class intends the method in the outer class to be called from the inner class. That works until a method with the same name is added to the base class of the inner class.

Nothing you can do about that as far as I can see..
 
Mark Griffin
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey Chris,

Dealing with the second code sample. It will compile. It is a bit contrived but it helped me figure out what method is called when an anonymous inner class calls a method that exists in its base class and in the outer class.

This code creates an instance of a class that extends BaseClass. The reference "b" is a reference to a "BaseClass" object so you can use it to call any method in "BaseClass". The syntax is kind of wild looking but that is a different story. Basically, instead of putting a semicolon right after the "new BaseClass()" you stick in an implementation of BaseClass followed by the semicolon.




Now say you add a method to the inner class called doCmd(). It would look like this:



You could not call doCmd() with the "b" reference. Like this wouldn't work: b.doCmd(). That's because "b" is a reference to an instance of BaseClass. You can call doCmd() from other methods in the inner class.

Is that as clear as mud?

-Mark


 
Chris Staten
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey Mark, thanks for the reply

Clear as mud? Without a doubt. Drinking water on the other hand, well�

Anyway, let me see if I get this right, I�ll go in order of the questions in my above post.

As for the inner class question, well it is there, it was just hard for me to see.

This creates a class called BaseClass and the code between the first curly brace and the last one with a semicolon is the code for the class. Right?



My semicolon question is answered as long as what I just said is true (I think). Because everything that comes after �BaseClass b = new BaseClass()� is still kind of a part of that statement, therefore it needs to be terminated with the semicolon. I think another way to look at this would be if the inner class did absolutely nothing and it was defined this way:
BaseClass b = new BaseClass (){ /* look mom, no code !*/ };



Well, I got this far thinking that I knew why the system.out.println command wouldn�t work, but I guess I�ve got nothing on that
[ October 01, 2004: Message edited by: Chris Staten ]
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Chris Staten:
This creates a class called BaseClass and the code between the first curly brace and the last one with a semicolon is the code for the class. Right?


Not fully correct: It creates an "anonymous inner class" (a class that has no name in the source code) with BaseClass as its superclass. It will get compiled to a class file named like OuterClass$1.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!