Sign in to follow this  
Zahlman

[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 this post


Link to post
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

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]

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this