2009-10-02 11 views
15

implementar tengo tres tipos Java como se define a continuación:javac se queja: no puede encontrar símbolo en la interfaz de enumeración

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

} 

(Este es casi exactamente el ejemplo dado en Effective Java 2nd ed. Artículo 30) El código anterior se compila y ejecuta muy bien en eclipse, pero con Sun javac me sale el siguiente error:

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

Si cambio de la línea 12 de Main.java de return func.call(values); a return ((Operation)func).call(values) que compila bien. Además, si pongo los tres tipos (Operation, Main y OperationDefinitions) juntos como tres subclases de una única clase principal, compila también bien.

Así que tengo soluciones para mi problema, pero me pregunto, ¿por qué javac requiere un molde aquí, pero eclipse no? ¿Es esto un error en javac o en eclipse?

He intentado tanto Sun javac 1.5.0_19 y 1.6.0_16

Respuesta

10

Podría ser un error en el javac del solar. func es un enum (incluso si ese enum implementa Operation) y la clase Enum no tiene un método call(). Para resolver el problema, sugiero cambiar la asignación:

Operation func = OperationDefinitions.CONCATENATE; 

Eso también dejará claro lo que espera: Es una operación, no un enum. El enum es solo una forma conveniente de recopilar todas las operaciones posibles (un contenedor si lo desea).

+2

+1 por estilo, normalmente eso sería lo correcto. Lo que no he explicado aquí es que esto es solo un pequeño fragmento del código real, y OperationDefinitions tiene funciones de miembros adicionales que no están en operación, como getHelp() y getDescription() – amarillion

+0

Sin mencionar que siempre debemos programar para interfaces no clases! getHelp y getDesctiption se deben definir en otra interfaz. Supongamos que tiene una interfaz como interfaz Helper {String getHelp(); String getDescription();} Para invocar getHelp() de la siguiente manera: Helper helper = OperationDefinitions.CONCATENATE; helper.getHelp(); – uthomas

0

Sospecho que esto es realmente un error en javac; OperationDefinitions definitivamente tiene tiene una llamada al método (abstracta) (java.util.List), ya que implementa la interfaz Operation. Y la definición de clase es válida, ya que todas las constantes proporcionan una implementación concreta de esta interfaz.

Una cosa que podría ser parcialmente responsable de esto, es que, a mi conocimiento, todos los métodos definidos en una interfaz deben ser públicos. Si realmente definiste el método call en la interfaz con el modificador de acceso predeterminado, esperaría que el compilador lo rechazara, pero si no lo hace, no me sorprendería ver problemas al final de la línea. Si esto fue un error tipográfico, está bien, pero si es así en tu código, intenta declararlo como público y ver si el problema desaparece.

+4

Todos los métodos en la interfaz son implícitamente abstractos y públicos. Si omite esos modificadores (que es recomendado por AFAIK), el compilador los agregará por usted. Si escribe cualquier otro modificador, obtendrá un error. –

2

Este es un error, como nos lo ha mostrado "Stephen Denne", pero si no puede hacer la actualización a una nueva versión (pero debería) ...Basta con retirar la inteface de OperationDefinitions y poner el método ...call(...) en la enumeración, así:

public abstract Object call(List params);

debería funcionar.

Cuestiones relacionadas