2

I design a class:

public class CustomEvent< P, T >
{
  /** Facade interface used for adopting user interfaces to our generic class. */
  public interface ICaller< P, T >
  {
    /** callback facade method. */
    void call( P parent, T callback, Object... objects );
  }

  /** Abstract class for simplifying naming in constructor.  */
  public abstract class Caller implements ICaller< P, T >{}

  /** Constructor. */
  public CustomEvent( final String name, final P parent, final Caller caller ){}
}

Now I want to create a instance of such class:

  public class TestClass
  {
    private final TestEvent mEventOnLoad;

    public TestClass()
    {   
      // ERROR here: No enclosing instance of type CustomEvent<P,T> is accessible. 
      // Must qualify the allocation with an enclosing instance of type 
      // CustomEvent<P,T> (e.g. x.new A() where x is an instance of CustomEvent<P,T>).
      mEventOnLoad = new TestEvent( "onLoad", this, new TestEvent.Caller() {
        public void call( TestClass parent, ITestCallbacks callback, Object... objects )
        {
          // some code here
        }
      } );
    }

    private class TestEvent extends CustomEvent< TestClass, ITestCallbacks >
    {
      public TestEvent( String name, TestClass parent, TestEvent.Caller caller )
      {
        super( name, parent, caller );
      }
    };
  }

Is it possible to somehow to workaround that? I want to simplify naming of the classes, instead of long generic declaration use short abstract class name which contains all needed type definitions?

I have a filling that it is possible... but I'm not very comfortable with Java yet...

Solution

    private class TestEvent extends CustomEvent< TestClass, ITestCallbacks >
    { 
      public final static TestEvent Instance = new TestEvent( null, null, null );

      public TestEvent( String name, TestClass parent, TestEvent.Caller caller )
      {
        super( name, parent, caller );
      }
    };

    public TestClass()
    {   
      mEventOnLoad = new TestEvent( "onLoad", this, TestEvent.Instance.new Caller() {
        public void call( TestClass parent, ITestCallbacks callback, Object... objects )
        {
          // some code here
        }
      } );
    }
Oleksandr Kucherenko
  • 1,921
  • 1
  • 17
  • 21
  • 1
    Possible duplicate of [Java - No enclosing instance of type Foo is accessible](http://stackoverflow.com/questions/9560600/java-no-enclosing-instance-of-type-foo-is-accessible) – Raedwald Mar 02 '16 at 22:39

3 Answers3

6

Caller needs to be declared static. Caller, as declared now, is an inner class, which means that it can only be created from an instance of an existing super class. For example, if you've got:

class A{
  class B{}
}

Then to create something of class B, you'd need:

A a = new A();
B b = new a.B();

That is because B is an inner class; it can only exist within the context of some A. You probably don't need it to be an inner class, so declare it as static to make it act just like a normal class. Or, remove if it's not needed.

heneryville
  • 2,853
  • 1
  • 23
  • 30
  • If you take a look on code, I use approach you recommend. It does not work. Generics & anonymous classes makes things harder to read but easier to use. – Oleksandr Kucherenko Nov 15 '11 at 01:06
2

If you're just trying to get your code to compile (mind you, you'd need to fix several issues with type safety and parameterising), try something like this:

public TestClass() {
    CustomEvent bla = new CustomEvent("name", null, null); // TODO: parameterise
    mEventOnLoad = new TestEvent("onLoad", this, bla.new Caller() {
        @Override
        public void call(Object parent, Object callback, Object... objects) {
            // some code here
        }
    });
}

What the error message was trying to say is that you need an instance (bla) to call new on. I'd suggest reading up on inner classes a bit ;-)

Amos M. Carpenter
  • 4,848
  • 4
  • 42
  • 72
  • Can not tell that `bla.new Caller` very intuitive syntax... But Thanks a lot such approach helps... – Oleksandr Kucherenko Nov 15 '11 at 00:36
  • Please note that I'm assuming your code is simply for your own benefit, to play around with different aspects of Java like generics and inner classes; my code above was not meant to be an example of good programming practice, it was just to give you an example of how to get it to work. Oh, and if you want intuitive syntax, try Smalltalk instead of Java ;-) – Amos M. Carpenter Nov 15 '11 at 00:40
  • code works, but ugly for use... I will better to search for another way. – Oleksandr Kucherenko Nov 15 '11 at 01:15
1

I'd recommend getting rid of the class Caller. It serves no useful purpose.

If you insist on keeping it, you need to make it a static class.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • definitely I will look for another approach. I try to simplify callbacks, but instead make them even harder. Compromise between transparency and efficiency, which I'm searching in my code, is very hard to find. Thanks for help in any case. – Oleksandr Kucherenko Nov 15 '11 at 01:08