Inner Classes a liability

B

Ben Wilson

Hi, I'm hoping someone out there is an expert and can share some
authoritative insights.

I'm working with inner classes in Java, and I'm finding myself unsatisfied
with the way they've been implemented, and frankly, somewhat alarmed. It is
true that an inner class can access the methods and object variables of its
enclosing class. However, it is also true that inner classes participate in
overriding - I can set up an inner class that overrides the members of its
enclosing class. However, inner classes can also be defined to extend
another class entirely.

Hello? I thought Java didn't support multiple inheritance but here it is!

Have a look at this sample code and tell me what's going on here:

//inners2.java

class inners2
{
void printMessage()
{
System.out.println("ladida");
}

public static void main(String[] args)
{
new outerclass01().new sucker().printMessage();
}
}

class outerclass01
{
void printMessage()
{
System.out.println("humdeedum");
}

class sucker extends inners2
{}
}

So there you go, what's the above code going to print when run? Is it
"ladida" or "humdeedum"?

From seeing this I get the feeling that not a lot of thought got put into
defining what it was exactly that inner classes were supposed to do. Anybody
know what the story is here?

Thanks,

Ben.
 
M

Michael Rauscher

Hi Ben,

Ben said:
Hi, I'm hoping someone out there is an expert and can share some
authoritative insights.

I'm working with inner classes in Java, and I'm finding myself unsatisfied
with the way they've been implemented, and frankly, somewhat alarmed. It is
true that an inner class can access the methods and object variables of its
enclosing class. However, it is also true that inner classes participate in
overriding - I can set up an inner class that overrides the members of its
enclosing class. However, inner classes can also be defined to extend
another class entirely.

Sure. But you cannot setup your inner class to override methods of its
outer class *and* extend another class.
Hello? I thought Java didn't support multiple inheritance but here it is!

No, it isn't here.
Have a look at this sample code and tell me what's going on here:

//inners2.java

class inners2
{
void printMessage()
{
System.out.println("ladida");
}

public static void main(String[] args)
{
new outerclass01().new sucker().printMessage();

you create an instance of sucker (subclass of inners2) and call it's
printMessage method. So, where's multiple inheritance?
}
}

class outerclass01
{
void printMessage()
{
System.out.println("humdeedum");
}

class sucker extends inners2
{}
}

So there you go, what's the above code going to print when run? Is it
"ladida" or "humdeedum"?

ladida of course since you created an instance of sucker.

Counterquestion: what do you get if you have the following in your main
method?

public static void main( String args[] ) {
Object o = new outerclass01().new sucker();

System.out.println( "is sucker: " + o instanceof sucker );
System.out.println( "is inners2: " + o instanceof inners2 );
System.out.println( "is outerclass01: "+o instanceof outerclass01 );
}

Michael
 
B

Ben Wilson

Hi, Michael
Sure. But you cannot setup your inner class to override methods of its
outer class *and* extend another class.

Actually, that's a bit my point. You can set up an inner class to override
methods of both the outer class *and* extend another class with ease.

Here - the modified version... (try it if you don't believe me...)

package temptests;

class inners2
{

void printMessage()
{
System.out.println("ladida");
}

public static void main(String[] args)
{
outerclass01.sucker t = new outerclass01().new sucker();
Object o = new outerclass01().new sucker();
t.printMessage();
t.prontMessage();
System.out.println("is sucker" + (o instanceof
temptests.outerclass01.sucker));
System.out.println("is inners2" + (o instanceof inners2));
System.out.println("is outerclass01" + (o instanceof outerclass01));

}

}


class outerclass01
{

void prontMessage()
{
System.out.println("hodihum");
}

class sucker extends inners2
{
void printMessage()
{
System.out.println("The Rain");
}

void prontMessage()
{
System.out.println("In Spain");
}

}

}

If you run this, you'll get to see "The Rain" "In Spain" and then true,
true, and false. There, have I just done something you thought was
impossible ;-)?

I do not believe Java was supposed to let this sort of thing happen. From
seeing this I get the feeling that not a lot of thought got put into
defining what it was exactly that inner classes were supposed to do. Anybody
know what the story is here?

Thanks,

Ben.
 
A

Adam

I do not believe Java was supposed to let this sort of thing happen.
From
seeing this I get the feeling that not a lot of thought got put into
defining what it was exactly that inner classes were supposed to do. Anybody
know what the story is here?

I'm having the same reservations about inner classes and
their possibilities. Once someone posted such a riddle here
(see below). I think it shows how bug prone can inner
(in this case - anonymous) classes be:

public class T
{
private final String name;
protected void prname() { System.out.println(name); }
T(String name) { this.name = name; }

public static void main(String[] args)
{
new T("main").doit();
}

private void doit()
{
new T("anonymous inner")
{
void method()
{
prname();
}
}.method();
}
}

What will be printed when you run it?
 
C

chris

Ben said:
From seeing this I get the feeling that not a lot of thought got put into
defining what it was exactly that inner classes were supposed to do.
Anybody know what the story is here?

The usual one - Microsoft had "extended" the Java language, and Sun felt
the need to offer an equivalent convenience in its own, "official" version
of the language. That's how most of the ill thought-out features you come
across in languages or applications get there.
 
B

Bjorn Abelli

...
Hello? I thought Java didn't support multiple
inheritance but here it is!

No, the inner class doesn't "inherit" the outer class.

However, it is seen as a kind of "outer scope" for the
inner class, and hence the methods from the outer class
are accessible for the inner class.

If the inner class has a method of its own with the
same signature as a method in the outer class, it
doesn't "override" it. It simply "hides" it.
class inners2
{
void printMessage()
{
System.out.println("ladida");
}

public static void main(String[] args)
{
new outerclass01().new sucker().printMessage();
}
}

class outerclass01
{
void printMessage()
{
System.out.println("humdeedum");
}

class sucker extends inners2
{}
}

So there you go, what's the above code going
to print when run? Is it
"ladida" or "humdeedum"?

Of course it is "ladida" as it's the result of the
method printMessage in the inner class, which it
inherited from "inners2".

As an evidence that the inner class doesn't inherit
the outer class, remove "extends inners2" from the
class sucker, and you will see that it won't even
compile on the line

new outerclass01().new sucker().printMessage();

....as "sucker" then doesn't even *have* a method printMessage.

FWIW, I still think you have a point in that inner classes is an "ugly" and
possibly "errorprone" concept. I never use it myself, as anything you can do
with inner classes can be solved with other means.

// Bjorn A
 
C

Chris Smith

Ben said:
Actually, that's a bit my point. You can set up an inner class to override
methods of both the outer class *and* extend another class with ease.

Your confusion comes primarily from misuse of the word "override". That
word has a specific meaning in Java. Because you've been talking about
overriding methods of the outer class, everyone who has responded has
been assuming that your inner class extends your outer class. If that
were the case, it could not also extend a different class.

It seems, though, that you're using "override" to refer to the masking
behavior by which a method declared in the smaller scope of an inner
class hides a method of the same name declared in the outer class.
That's not overriding a method: it's not polymorphic, and method
resolution is strictly limited to lexical scope and determined by the
compiler.

A couple points about inner classes:

1. If your inner class is closely related to your outer class, then yes
things can get confusing. That's because you've essentially declared
two different relationships between the two classes (inner/outer, and
inheritance), and you're apparently having trouble keeping the two kinds
of relationships straight.

Fortunately, I've rarely if ever seen a good reason for an inner class
to extend its outer class.

2. It's best to avoid ambiguous method names where you share a method
name between inner and outer classes. Since the inner type is a
dependent concept on its outer class, that's always entirely possible.
Here - the modified version... (try it if you don't believe me...)

And, as predicted, the inner class (sucker), extends only one other
class (inners2). It does not extend outerclass01, and hence can't
override its methods. However, sucker does indeed lexically hide the
implementation of prontMessage in outerclass01, so that a call to
sucker.prontMessage will resolve at compile-time to the sucker
implementation. Since this happens at compile-time, it is so resolved
before any resolution of method overrides; so if you an instance of a
subclass of sucker that overrides the prontMessage method, then the
subclass implementation would be called.
I do not believe Java was supposed to let this sort of thing happen. From
seeing this I get the feeling that not a lot of thought got put into
defining what it was exactly that inner classes were supposed to do. Anybody
know what the story is here?

Perhaps it will be illustrative to understand that the following doesn't
work. It doesn't work specifically because the resolution of methods
between inner and outer classes is *not* based on inheritance.

public class Test
{
public static void main(String[] args)
{
new Test2().new TestInner().printMessage();
}
}

class Test2
{
public void printMessage()
{
System.out.println("Test message");
}

class TestInner
{
}
}

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
M

Michael Rauscher

Hi Ben,

Ben said:
Hi, Michael




Actually, that's a bit my point. You can set up an inner class to override
methods of both the outer class *and* extend another class with ease.

No, you can't (see below)

Code:
[QUOTE]
If you run this, you'll get to see "The Rain" "In Spain" and then true,
true, and false. There, have I just done something you thought was
impossible ;-)?[/QUOTE]

No, you haven't. That are exactly the results I'd expect.

You get true, true and false. What does this mean?

Your sucker-object is an instance of outerclass01.sucker (of course) its
an instance of inners2 (since outerclass01.sucker extends inners2) but
it is not an instance of outerclass01.

The latter means that sucker isn't a subclass of outerclass01. And since
sucker doesn't extend outerclass01 you didn't overwrite any method of
outerclass01.

Therefore this has nothing to do with multiple inheritance. sucker
extends inners2, sucker does neither extend outerclass01 nor does it
overwrite methods of outerclass01...

Bye
Michael
 
X

xarax

Michael Rauscher said:
Hi Ben,

Ben said:
Hi, Michael




Actually, that's a bit my point. You can set up an inner class to override
methods of both the outer class *and* extend another class with ease.

No, you can't (see below)

Code:
[QUOTE]
If you run this, you'll get to see "The Rain" "In Spain" and then true,
true, and false. There, have I just done something you thought was
impossible ;-)?[/QUOTE]

No, you haven't. That are exactly the results I'd expect.

You get true, true and false. What does this mean?

Your sucker-object is an instance of outerclass01.sucker (of course) its
an instance of inners2 (since outerclass01.sucker extends inners2) but
it is not an instance of outerclass01.

The latter means that sucker isn't a subclass of outerclass01. And since
sucker doesn't extend outerclass01 you didn't overwrite any method of
outerclass01.

Therefore this has nothing to do with multiple inheritance. sucker
extends inners2, sucker does neither extend outerclass01 nor does it
overwrite methods of outerclass01...

Bye
Michael[/QUOTE]

Inner classes are not a form of multiple inheritance
of implementation nor interface. The compiler creates
a hidden field that contains a reference to the outer
class instance. Whenever the inner class has a method
call or refers to field of the enclosing instance, the
hidden reference is used.

Also, you cannot assign a reference from the inner
class to a variable or field that is declared of the
outer class type.
 
L

Lasse Reichstein Nielsen

Adam said:
I'm having the same reservations about inner classes and
their possibilities. Once someone posted such a riddle here
(see below). I think it shows how bug prone can inner
(in this case - anonymous) classes be:
What will be printed when you run it?

It will print "anonymous inner".

The point of confuzion is that Java doesn't have textual scope. The
binding of an identifier is not necessarily the nearest textually
enclosing declaration of that name.

Another example:
----
class B {
String foo = "bar";
}

class A {
int foo = 37;
int main(String[] args) {
boolean foo = false;
new B() {
method() { System.out.println(foo); }
}.method();
}
}
----
There are plenty of declarations of variables called foo around the
call to println, but the one actually used is not diretly in scope.

It's a mind-bender for sure, but once you get the knack of it, it
won't bite you too often :)

/L
 
R

Robert

Ben said:
Hi, I'm hoping someone out there is an expert and can share some
authoritative insights.

I'm working with inner classes in Java, and I'm finding myself unsatisfied
with the way they've been implemented, and frankly, somewhat alarmed. It is
true that an inner class can access the methods and object variables of its
enclosing class. However, it is also true that inner classes participate in
overriding - I can set up an inner class that overrides the members of its
enclosing class. However, inner classes can also be defined to extend
another class entirely.

Hello? I thought Java didn't support multiple inheritance but here it is!

Have a look at this sample code and tell me what's going on here:

//inners2.java

class inners2
{
void printMessage()
{
System.out.println("ladida");
}

public static void main(String[] args)
{
new outerclass01().new sucker().printMessage();
}
}

class outerclass01
{
void printMessage()
{
System.out.println("humdeedum");
}

class sucker extends inners2
{}
}

So there you go, what's the above code going to print when run? Is it
"ladida" or "humdeedum"?

From seeing this I get the feeling that not a lot of thought got put into
defining what it was exactly that inner classes were supposed to do. Anybody
know what the story is here?

Thanks,

Ben.
Maybe good timing on JDJ's part.

There is an article called "Strategies for Securing Java Code". Rule #1
is "Avoid Using Inner Classes". A good read and here is the link to it:

http://sys-con.com/story/?storyid=44375&DE=1
 
C

Chris Smith

Robert said:
Maybe good timing on JDJ's part.

There is an article called "Strategies for Securing Java Code". Rule #1
is "Avoid Using Inner Classes". A good read and here is the link to it:

http://sys-con.com/story/?storyid=44375&DE=1

Or perhaps a really bad article. I don't read JDJ much, so I'm
struggling not to judge the whole magazine on the fact that this load of
balogna got through their editing process...

I'll constrain my criticism to the inner classes issue. In particular,
the article makes a few assumptions:

1. That package access is insecure. Aside from the inconsequential
misinformation about the treatment of private field access from inner
classes (which really is inconsequential, as the result is a package-
access member either way), there's nothing wrong with package access for
security!

I'd go as far as saying that anything stronger than package access
(i.e., private access) is nice from a code maintenance standpoint, but
absolutely pointless to someone concerned about security. The authors
say they are concerned about package access because someone could
conceivably provide code that declares the same package as the security-
sensitive code. The authors mention package-sealing... that security
feature that's used effectively by the *entire* core API to prevent
exactly these kinds of security issues... but imply that it's a "second-
best" kind of answer. Not the case; if you want to secure access by
untrusted code to an API, it *has* to be in a sealed package.

The only remaining possibility, then, is concern about someone replacing
the existing implementation... a task which requires the kind of access
to the system that makes security completely moot!

Basically, if package access is broken from a security standpoint, then
Java is broken from a security standpoint. So if the authors really
believe what they say, then they need to stop using Java for security-
sensitive code. Of course, that won't really be necessary because they
are wrong.

2. The basic assumption that protection is needed against an attacker
running arbitrary bits of your code. This general concept fails
miserably. Any attacker who can run arbitrary bits of your code has
already won. Period. "Full stop" (if you're British). End of story.
If the authors are concerned about untrusted code running under a
security manager, then fine... but shouldn't they mention using the
security manager in that case?

Truth is, using inner classes is not a security risk. Failing to take
basic precautionary steps such as sealing security-sensitive packages in
the presence of untrusted code, on the other hand, is definitely a
security risk.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
B

Ben Wilson

To everyone who has helped me by replying to this, thank you!

My confusion started with the explanation of inner classes as "getting
access to the members of its enclosing class". From this I assumed that this
access was just made available, also to the inner class's callable
interface. In other words, I thought it was bigger than it actually was.

To use the example from Chris Smith:

public class Test
{
public static void main(String[] args)
{
new Test2().new TestInner().printMessage();
}
}

class Test2
{
public void printMessage()
{
System.out.println("Test message");
}

class TestInner
{
}
}


Yes, I can see now that this doesn't work. However, the call here to
printMessage(), had it been done within the class TestInner, would have.

The principles of "hiding" members from the outer class from within the
inner class have many parallels with overriding, so it is easy to get
confused. My dissatisfaction started because I realised I could "hide" a
method from the outer class by making one with an identical signature from
an inner class, but once I did that I could never actually get a-hold of the
outer class with something like "super". But more about this later.

First, two observations:
First observation: the literature makes a *real* lousy job of explaining
this. Take Heller&Roberts book "Complete Java 2 Certification Study Guide
Fourth Edition". When they talk about reusing method names, very
specifically, they say "As you construct classes and add methods to them, in
some circumstances you will want to re-use the same name for a method. You
can do so two ways with Java. Re-using the same method name with different
arguments and perhaps a different return type is known as overloading. Using
the same method name with identical arguments and return type is known as
overriding." Apparantly this statement is incorrect or at best incomplete -
there is also this "hiding" thing. Since what I was doing was using the same
method name with identical arguments and return type, well, it just *had* to
be overriding, right? Well, sure shows me!

As a second example, take Peter van der Linden's book "Just Java 2 - Fifth
edition". He says, in his chapter on Polymorphism: "Polymorphism is a
complicated name for a straightforward concept. It is Greek for 'many
shapes' and it merely means using the same one name to refer to different
methods. 'Name reuse' would be a better term. There are two types of
polymorphism in Java: the really easy kind (overloading) and the interesting
kind (overriding)." Same thing here, there's nothing on this hiding trick
you do with inner classes.

Second observation, this "hiding" principle is still iffy. Even if it it's
true that an inner class does not override the methods of its outer class
(as Chris and others have demonstrated) still it is possible for an inner
class to extend one of the methods of the outer class, much like a subclass
would do for its parent. Fortunately I read a bit from Bruce Eckel's book
where he explains this - and I've made a sample program to demonstrate:

package temptests;

class inners2
{

void printMessage()
{
System.out.println("hidiho");
}

public static void main(String[] args)
{

outerclass01 oc001 = new outerclass01();
outerclass01.sucker t2 = oc001.new sucker();
t2.lemmeSee();

}
}


class outerclass01
{

void printMessage()
{
System.out.println("deedledeedledeedle");
}

class sucker extends inners2
{

void printMessage()
{
System.out.println("feefifofum");
}

void lemmeSee()
{
printMessage();
super.printMessage();
outerclass01.this.printMessage();
}

}

}


The output is "feefifofum" "hidiho" and "deedledeedledeedle". This mechanism
enables me to extend methods with identical names, coming from two wholly
unrelated classes (outerclass01 and inners2). While it's great that this
sort of stuff is possible, I do believe, however, that it violates the
spirit of what they were trying to do when they specified no multiple
inheritance in Java.

I would be interested if somebody strongly disagreed with this.

Thanks,

Ben.





Ben Wilson said:
Hi, I'm hoping someone out there is an expert and can share some
authoritative insights.

I'm working with inner classes in Java, and I'm finding myself unsatisfied
with the way they've been implemented, and frankly, somewhat alarmed. It is
true that an inner class can access the methods and object variables of its
enclosing class. However, it is also true that inner classes participate in
overriding - I can set up an inner class that overrides the members of its
enclosing class. However, inner classes can also be defined to extend
another class entirely.

Hello? I thought Java didn't support multiple inheritance but here it is!

Have a look at this sample code and tell me what's going on here:

//inners2.java

class inners2
{
void printMessage()
{
System.out.println("ladida");
}

public static void main(String[] args)
{
new outerclass01().new sucker().printMessage();
}
}

class outerclass01
{
void printMessage()
{
System.out.println("humdeedum");
}

class sucker extends inners2
{}
}

So there you go, what's the above code going to print when run? Is it
"ladida" or "humdeedum"?

From seeing this I get the feeling that not a lot of thought got put into
defining what it was exactly that inner classes were supposed to do. Anybody
know what the story is here?

Thanks,

Ben.
 
T

Tony Morris

It was I who posted that case, and it was to demonstrate the question:
"Are private members inherited ?"

--
Tony Morris
(BInfTech, Cert 3 I.T.)
Software Engineer
(2003 VTR1000F)
Sun Certified Programmer for the Java 2 Platform (1.4)
Sun Certified Developer for the Java 2 Platform


Adam said:
I do not believe Java was supposed to let this sort of thing happen. From
seeing this I get the feeling that not a lot of thought got put into
defining what it was exactly that inner classes were supposed to do. Anybody
know what the story is here?

I'm having the same reservations about inner classes and
their possibilities. Once someone posted such a riddle here
(see below). I think it shows how bug prone can inner
(in this case - anonymous) classes be:

public class T
{
private final String name;
protected void prname() { System.out.println(name); }
T(String name) { this.name = name; }

public static void main(String[] args)
{
new T("main").doit();
}

private void doit()
{
new T("anonymous inner")
{
void method()
{
prname();
}
}.method();
}
}

What will be printed when you run it?
 
A

Adam

Tony Morris said:
It was I who posted that case, and it was to demonstrate the question:
"Are private members inherited ?"

Sorry, Tony for not mentioning you. I just could'n remember.
Anyway, it's a great example for this topic too,
presenting confusion that may arise when
using inner/anonymous classes.

Adam
 
C

Chris Smith

Ben said:
First, two observations:
First observation: the literature makes a *real* lousy job of explaining
this.

Yes, indeed. For many of us who've been around since Java 1.0.2 (and
that includes many of those who write books), it seems natural to
describe the old behavior of classes as "normal", and just know that
nested/inner classes are the exception. It's a bad habit, and should be
broken. You'll see the same thing regarding access specifiers: many
books will give you a blanket statement that classes can only have
public or package access, and then mention in chapter 17 somewhere that
nested classes can have the full range of private, package, protected,
or public just like any other member.

It's good to get the difference between overriding and overloading down;
but it only applies in cases where you're working with instance methods
declared in a common supertype. For static methods, only overloading
applies. For outer class methods, I'd wonder if use of the word
"overloading" is justified... but the behavior is the same as if it
were. The difference in the latter is really only conceptual in nature.
As a second example, take Peter van der Linden's book "Just Java 2 - Fifth
edition". He says, in his chapter on Polymorphism: "Polymorphism is a
complicated name for a straightforward concept. It is Greek for 'many
shapes' and it merely means using the same one name to refer to different
methods. 'Name reuse' would be a better term. There are two types of
polymorphism in Java: the really easy kind (overloading) and the interesting
kind (overriding)."

Well, frankly I don't know what Peter was thinking. I respect Peter's
opinion on most topics (and he used to be a fairly active participant in
this newsgroup), but this is just dead wrong. Polymorphism has nothing
to do with method overloading. It is the property of runtime dispatch
of overridden methods.
Second observation, this "hiding" principle is still iffy. Even if it it's
true that an inner class does not override the methods of its outer class
(as Chris and others have demonstrated) still it is possible for an inner
class to extend one of the methods of the outer class, much like a subclass
would do for its parent.

I still disagree with the terminology here.

You should think of the ability of an inner class to call methods of its
outer class as a convenience offered to you by the compiler, and nothing
more. Any meaningful relationship between a method in an inner class
and a similarly named method in an outer class is a myth. Exactly like
any relationship between mutually overloaded methods is a myth. The
sooner you understand that, the sooner this will make sense to you.

In your example, there are exactly two classes that have a definite
relationship, and they are inners2 and sucker. outerclass01 is just
there, and is used by sucker to delegate a method call. That's it. The
fact that the method 'printMessage' in sucker/inners2 has the same name
and parameters as printMessage in outerclass01 is a coincidence. In
fact, it has the unfortunate side-effect that it's harder to actually
call that printMessage method, requiring you to use "OuterClass.this."
to resolve the ambiguity.
The output is "feefifofum" "hidiho" and "deedledeedledeedle". This mechanism
enables me to extend methods with identical names, coming from two wholly
unrelated classes (outerclass01 and inners2). While it's great that this
sort of stuff is possible, I do believe, however, that it violates the
spirit of what they were trying to do when they specified no multiple
inheritance in Java.

I really believe not. The similarity in name is coincidental, and has
no semantic significance. The purpose of disallowing multiple
inheritance in Java was to avoid overly complex method dispatch. There
is no dispatch here; the compiler knows entirely at compile-time exactly
which method you are calling.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

John C. Bollinger

Ben said:
My confusion started with the explanation of inner classes as "getting
access to the members of its enclosing class". From this I assumed that this
access was just made available, also to the inner class's callable
interface. In other words, I thought it was bigger than it actually was.
[...]

The principles of "hiding" members from the outer class from within the
inner class have many parallels with overriding, so it is easy to get
confused. My dissatisfaction started because I realised I could "hide" a
method from the outer class by making one with an identical signature from
an inner class, but once I did that I could never actually get a-hold of the
outer class with something like "super". But more about this later.

Well, "super" itself doesn't work, and oughtn't, but a construct of the
form Outer.this does. You even offer your own example later.
First, two observations:
First observation: the literature makes a *real* lousy job of explaining
this. Take Heller&Roberts book "Complete Java 2 Certification Study Guide
Fourth Edition". When they talk about reusing method names, very
specifically, they say "As you construct classes and add methods to them, in
some circumstances you will want to re-use the same name for a method. You
can do so two ways with Java. Re-using the same method name with different
arguments and perhaps a different return type is known as overloading. Using
the same method name with identical arguments and return type is known as
overriding." Apparantly this statement is incorrect or at best incomplete -
there is also this "hiding" thing. Since what I was doing was using the same
method name with identical arguments and return type, well, it just *had* to
be overriding, right? Well, sure shows me!

No, you are applying the statement too broadly. You seem to have not
grasped the fact that for all intents and purposes, an inner class is a
*seperate* class from its containing class[es]. It has special access
to its containing class[es], true, but that's irrelevant. When you add
a method to an inner class you are not adding it to any containing
class, so you H&R's statement does not apply.
As a second example, take Peter van der Linden's book "Just Java 2 - Fifth
edition". He says, in his chapter on Polymorphism: "Polymorphism is a
complicated name for a straightforward concept. It is Greek for 'many
shapes' and it merely means using the same one name to refer to different
methods. 'Name reuse' would be a better term. There are two types of
polymorphism in Java: the really easy kind (overloading) and the interesting
kind (overriding)." Same thing here, there's nothing on this hiding trick
you do with inner classes.

Again, same comment: methods on an inner class are not methods on any
containing class. Polymorphism is an aspect of relationships among
classes. Unless the inner class extends a containing class (rarely good
or appropriate) the concept of polymorphism is just not germane to the
relationship between inner classes and their containing classes.
Second observation, this "hiding" principle is still iffy. Even if it it's
true that an inner class does not override the methods of its outer class
(as Chris and others have demonstrated) still it is possible for an inner
class to extend one of the methods of the outer class, much like a subclass
would do for its parent.

No. Perhaps we're having another terminology problem, but the word
"extend" has specific meaning in the context of Java: the relationships
between a class and each of its superclasses. As we've been discussing,
a class can override methods inherited from any class it extends, and it
can offer overloaded versions of those methods.

You are quite right that under certain circumstances an inner class may
override a method inherited from its superclass, which itself hides a
method of the containing class. The confusing mess that results is not
a language problem, it is a language usage problem. Good designs,
including those that use inner classes, do not exhibit such problems.
You can shoot yourself in the foot in any language (see
http://www-users.cs.york.ac.uk/~susan/joke/foot.htm, or any of the many
variations available on the web) but that doesn't mean that all computer
languages are therefore flawed.

John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top