Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Java (http://www.velocityreviews.com/forums/f30-java.html)
-   -   Inner Classes a liability (http://www.velocityreviews.com/forums/t132895-inner-classes-a-liability.html)

Ben Wilson 04-25-2004 11:35 PM

Inner Classes a liability
 
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.





Michael Rauscher 04-26-2004 12:28 AM

Re: Inner Classes a liability
 
Hi Ben,

Ben Wilson schrieb:
> 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


Ben Wilson 04-26-2004 06:30 AM

Re: Inner Classes a liability
 
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.








Adam 04-26-2004 07:15 AM

Re: Inner Classes a liability
 
> 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?



chris 04-26-2004 07:57 AM

Re: Inner Classes a liability
 
Ben Wilson wrote:

> 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.

--
Chris Gray chris@kiffer.eunet.be
/k/ Embedded Java Solutions


Bjorn Abelli 04-26-2004 10:21 AM

Re: Inner Classes a liability
 
"Ben Wilson" wrote...

> 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



Chris Smith 04-26-2004 02:19 PM

Re: Inner Classes a liability
 
Ben Wilson wrote:
> 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

Michael Rauscher 04-26-2004 04:05 PM

Re: Inner Classes a liability
 
Hi Ben,

Ben Wilson schrieb:
> 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.


No, you can't (see below)

[code]
>
> 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 ;-)?


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


xarax 04-26-2004 06:51 PM

Re: Inner Classes a liability
 
"Michael Rauscher" <michlmann@gmx.de> wrote in message
news:c6jbl3$iuu$05$1@news.t-online.com...
> Hi Ben,
>
> Ben Wilson schrieb:
> > 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.

>
> No, you can't (see below)
>
> [code]
> >
> > 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 ;-)?

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


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.



Lasse Reichstein Nielsen 04-26-2004 08:13 PM

Re: Inner Classes a liability
 
"Adam" <NOTFORSPAM.a_szczeblewski@poczta.onet.pl> writes:

> 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
--
Lasse Reichstein Nielsen - lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'


All times are GMT. The time now is 08:55 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.