# [java] Inner classes - outer class method is hidden?

## Recommended Posts

Zahlman    1682
Consider the following:
class Outer {
public void doSomething(int x) { System.out.println(x); }

class Inner {
public void doSomething() {
// Outer.doSomething(42); <-- doesn't work; doSomething() is not static
// doSomething(42); <-- doesn't work; the compiler looks for the method in
// Outer.Inner first, and complains that it can't be applied to (int)
// this.doSomething(42); <-- doesn't work; same problem
}
}
}


How do I call the Outer's doSomething() from within the Inner's doSomething()? The only thing I found that compiles is to have Inner extend Outer and use super. , but this makes no logical sense for my design at all. (Actually, I can't imagine a case where it would ever make sense.) EDIT: The following works, but I still can't believe I would have to do something like this:
class Outer {
public void doSomething(int x) { System.out.println(x); }
private void doSomething_redirect(int x) { doSomething(x); }

class Inner {
public void doSomething() {
doSomething_redirect(42);
}
}
}


The thing is, in the actual code, the analogue of 'doSomething' is the only reasonable name for the method... and a large part of the purpose of Inner is to encapsulate a parameter for the doSomething call.

##### Share on other sites
Alpha_ProgDes    6921
does
class Outer {  public void doSomething(int x) { System.out.println(x); }  class Inner {    public void doSomething() {      // Outer.doSomething(42); <-- doesn't work; doSomething() is not static      // doSomething(42); <-- doesn't work; the compiler looks for the method in      // Outer.Inner first, and complains that it can't be applied to (int)      // this.doSomething(42); <-- doesn't work; same problem      Outer.this.doSomething(42); // <-- this should work!    }  }}
works?

idea came from: http://bytes.com/groups/java/16382-inner-class-referencing-outer-classes-members

edit: for clarity

[Edited by - Alpha_ProgDes on May 1, 2009 12:08:15 PM]

##### Share on other sites
OrangyTang    1298
Like this:
class Outer {  public void doSomething(int x) { System.out.println(x); }  class Inner {    public void doSomething() {      Outer.this.doSomething(42);    }  }}

Edit: too slow, but I've tested it and it does work.

##### Share on other sites
Zahlman    1682
Excellent, thank you. Now I can get on with the rest of this epic refactoring. :)

(For the curious: the actual Outer represents a data buffer that can be viewed alternately as a byte[], short[] or int[], and the actual Inner represents a pseudo-iterator with some other useful functionality. It's quite irritating how java.util.Arrays doesn't provide anything useful here, really...)

##### Share on other sites
OrangyTang    1298
Quote:
 Original post by Zahlman(For the curious: the actual Outer represents a data buffer that can be viewed alternately as a byte[], short[] or int[], and the actual Inner represents a pseudo-iterator with some other useful functionality. It's quite irritating how java.util.Arrays doesn't provide anything useful here, really...)

Have you seen ByteBuffer and it's related classes?

##### Share on other sites
Zahlman    1682
:O More excellence. I'll update to use that as soon as I get this set of changes working. (That's the problem with javadoc - all generated documentation, really: it tells you what a class does, but it doesn't tell you which class does what you're trying to do.) I wonder why they don't offer concrete implementations and demand you use the factory functions instead, though. And I'm still rather fond of the pseudo-iterator functionality.

Next question: How do I check if two instances of Inner have the same Outer instance? I.e. I'm trying to implement .equals() for Inner, and

public boolean equals(Object other) {	if (!(other instanceof Inner)) return false;	Inner i = (Inner)other;	// Outer.this == i.this // doesn't work	// Outer.this == Outer.i // doesn't work}

Again the only thing that seems to be working is to route through a private method.

##### Share on other sites
OrangyTang    1298
The only method I can find that works is via reflection:
		public boolean equals(Object rhs)		{			try			{				 Outer otherOuter = (Outer)rhs.getClass().getDeclaredField("this\$0").get(rhs);				 				 return Outer.this == otherOuter;			}			catch (NoSuchFieldException e) {}			catch (IllegalAccessException e) {}			 			return false;		}

Which is probably slower than creating a private accessor, but might be preferable depending on what you're doing.

##### Share on other sites
Zahlman    1682
Ick. I'll stick with the accessor for now. You'd think there'd be a keyword analogous to 'super' for this, like 'container' or 'outer' or something...