2011-11-14 5 views
1

タイプのエンクロージングインスタンス:Javaコンパイラはエラーを与えていない - 私はクラス設計

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){} 
} 

は、今私は、このようなクラスのインスタンスを作成します:

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); 
     } 
    }; 
    } 

を、それは何とか回避することは可能ですがそれ?長いジェネリック宣言の代わりに、クラスの命名を簡素化したい、すべての必要な型定義を含む短い抽象クラス名を使用する?

ソリューション

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 
     } 
     }); 
    } 
+1

[Java - Foo型の囲むインスタンスはありません](http://stackoverflow.com/questions/9560600/java-no-enclosing) -instance-of-type-foo-is-accessible) – Raedwald

答えて

2

あなたは自分のコードをコンパイルするために取得しようとしている場合は(あなたの心は、あなたが型の安全性およびパラメータ化していくつかの問題を修正する必要があるだろう)、このような何かを試してみてください。

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 
     } 
    }); 
} 

どのようなエラーメッセージには、newを呼び出すためにインスタンス(bla)が必要であるというメッセージが表示されました。

+0

'bla.new Caller'は非常に直観的な構文だとは言えません...しかし、ありがとうございました。このようなアプローチは助けになります... –

+0

あなたのコードはあなたの利益のためだけであると仮定しています。ジェネリックスや内部クラスのようなJavaの。上記の私のコードは良いプログラミングの練習の例ではありませんでしたが、それを動作させる方法の例を伝えることだけでした。ああ、直感的な構文が必要な場合は、Javaの代わりにSmalltalkを試してみてください;-) –

+0

コードは動作しますが、使用するには醜いです...私は別の方法で検索する方が良いでしょう。 –

1

を、私はそれが可能であることを充填を持っている...しかし、私は、Javaと非常に快適ではないよ、まだ...私は取り払うお勧めしますクラスCaller。それは有用な目的を果たさない。

あなたがそれを保つことを主張するならば、静的なクラスにする必要があります。

+0

私は別の方法を間違いなく探します。コールバックを単純化しようとしますが、代わりにコールバックをさらに難しくします。私のコードで探している透明性と効率性との間の妥協は、見つけるのが非常に難しいです。いずれにしても助けてくれてありがとう。 –

5

呼び出し元を静的宣言する必要があります。 Callerは、現在宣言されているように、内部クラスです。つまり、既存のスーパークラスのインスタンスからのみ作成できます。たとえば、あなたが持っている場合:

class A{ 
    class B{} 
} 

はその後、クラスBの何かを作成するには、必要があるでしょう:

Bは内部クラスであるためである
A a = new A(); 
B b = new a.B(); 

。いくつかのAの文脈の中にしか存在することはできません。おそらく、それが内部クラスである必要はありません。したがって、通常のクラスのように動作させるために静的として宣言します。または、必要がない場合は削除します。

+0

コードを見てみると、私はあなたが推奨するアプローチを使用します。それは動作しません。ジェネリッククラスと匿名クラスは、物事を読みにくく使いやすくします。 –

関連する問題