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

Started by
6 comments, last by Zahlman 14 years, 11 months ago
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.
Advertisement
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

better info at: http://www.google.com/url?sa=t&source=web&ct=res&cd=4&url=http%3A%2F%2Fen.wikibooks.org%2Fwiki%2FJava_Programming%2FNested_Classes&ei=Ni_7SbX6C4b8swOi1ZzeAQ&usg=AFQjCNGuGLtk1Cjhikh8nysZNXPI8w0Fwg

edit: for clarity

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

Beginner in Game Development?  Read here. And read here.

 

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.
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...)
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?
: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.
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.
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...

This topic is closed to new replies.

Advertisement