2009-10-02 4 views
15

を実装する列挙型のシンボルを見つけることができないの下に定義されている:javacは文句を言う:私は3つのJavaの型を持っているインタフェース

Main.java:

import java.util.Arrays; 
import java.util.List; 

public class Main 
{ 
    private Object callFunction() 
    { 
     OperationDefinitions func = OperationDefinitions.CONCATENATE; 
     List<Object> values = Arrays.asList(new Object[] {"ABC", "-", "DEF"}); 
     return func.call (values); 
    } 

    public static void main (String[] args) 
    { 
     Main main = new Main(); 
     System.out.println (main.callFunction()); 
    } 
} 

Operation.java

import java.util.List; 

public interface Operation 
{ 
    abstract Object call(List<Object> params); 
} 

OperationDefinitions.java

import java.util.List; 

enum OperationDefinitions implements Operation 
{ 
    CONCATENATE() { 
     public Object call(List<Object> params) 
     { 
      StringBuilder builder = new StringBuilder(); 
      for (Object param : params) builder.append((String)param); 
      return builder.toString(); 
     } 
    }, 
    ; 

} 

(これは、ほぼ正確にEffective Java 2nd edで与えられた例です。項目30) コンパイル上記のコードと日食でうまく動作しますが、Sunのjavacので、私は次のエラーを取得する:

Main.java:12: cannot find symbol 
symbol : method call(java.util.List<java.lang.Object>) 
location: class OperationDefinitions 
     return func.call (values); 
         ^
1 error 

私はreturn func.call(values);からreturn ((Operation)func).call(values)にMain.javaの行12を変更した場合、それは罰金コンパイルします。さらに、3つのタイプ(Operation、Main、OperationDefinitions)を1つのメインクラスの3つのサブクラスとしてまとめれば、それもうまくコンパイルされます。

問題の回避策がありますが、なぜjavacがここでキャストする必要がありますか?これはjavacまたはeclipseのバグですか?

私はそれは、Sunのjavacのバグかもしれない日のjavacの1.5.0_19および1.6.0_16

答えて

10

の両方を試してみました。 funcenumであり(enumOperationを実装していても)、Enumクラスのメソッドはcall()ではありません。

Operation func = OperationDefinitions.CONCATENATE; 

も、あなたが期待するもの、それを明確にします::操作、ないenum問題を解決するために、私は割り当てを変更することをお勧めします。 enumは、可能なすべての操作(必要に応じてコンテナ)を収集する便利な方法です。

+2

+1スタイルの場合、通常は正しいことです。私がここで説明していないのは、これは実際のコードのほんの一部であり、OperationDefinitionsはgetHelp()やgetDescription()のように、Operationにはない特別なメンバ関数を持っているということです。 – amarillion

+0

インタフェースではクラスではありません! getHelpおよびgetDesctiptionは別のインタフェースで定義する必要があります。 インターフェースヘルパー{String getHelp();のようなインターフェースを持っているとします。 String getDescription();} したがって、次のようにgetHelp()を呼び出すことができます: Helper helper = OperationDefinitions.CONCATENATE; helper.getHelp(); – uthomas

0

これは実際にはjavacのバグだと思われます。 OperationDefinitions間違いなくは、Operationインターフェイスを実装しているため、(抽象的)メソッド呼び出し(java.util.List)を持っています。すべての定数がこのインタフェースの具体的な実装を提供するので、クラス定義は有効です。

これに部分的に責任があることは、私の知る限りでは、インタフェースで定義されたすべてのメソッドは公開されている必要があります。実際にcallメソッドをデフォルトのアクセス修飾子付きのインタフェースで定義した場合、コンパイラはそれを拒否することを期待していますが、そうでなければ、問題をラインで見ても驚かないでしょう。これがタイプミスであっても問題ないのであれば、あなたのコードでそれを宣言し、問題がなくなるのを見てみてください。

+4

インターフェイス内のすべてのメソッドは、暗黙的に抽象的な公開です。これらの修飾子(AFAIKを推奨)を省略すると、コンパイラによってそれらが追加されます。他の修飾語を書くとエラーになります。 –

2

「Stephen Denne」が私たちに示したように、これはバグですが、新しいバージョンへの更新はできませんが...ただ、OperationDefinitionsからintefaceをを削除して、このように、列挙型の方法...call(...)を置く:

public abstract Object call(List params);

動作するはずです。

関連する問題