2012-05-11 20 views
6

Me di cuenta de que AbstractMethodError se produjo al ejecutar los siguientes códigos.AbstractMethodError se produjo cuando el método privado del paquete reemplaza

package javapkg; 

public abstract class JavaClass{ 
    abstract String foo(int b); 

    public String bar(int b){ 
    return foo(b); 
    } 
} 
package scalapkg 

import javapkg._ 

class ScalaClass extends JavaClass{ 
    def foo(a:Int) = a.toString 
} 

object Main extends App{ 
    println(new ScalaClass().bar(10)) 
} 
[error] (run-main) java.lang.AbstractMethodError: javapkg.JavaClass.foo(I)Ljava/lang/String; 
java.lang.AbstractMethodError: javapkg.JavaClass.foo(I)Ljava/lang/String; 
at javapkg.JavaClass.bar(JavaClass.java:7) 
at scalapkg.Main$delayedInit$body.apply(ScalaClass.scala:10) 
at scala.Function0$class.apply$mcV$sp(Function0.scala:34) 
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) 
at scala.App$$anonfun$main$1.apply(App.scala:60) 
at scala.App$$anonfun$main$1.apply(App.scala:60) 
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59) 
at scala.collection.immutable.List.foreach(List.scala:76) 
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:30) 
at scala.App$class.main(App.scala:60) 
at scalapkg.Main$.main(ScalaClass.scala:9) 
at scalapkg.Main.main(ScalaClass.scala) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
java.lang.RuntimeException: Nonzero exit code: 1 
at scala.sys.package$.error(package.scala:27) 

Es esto un error o una especificación?

P.S. Scala versión 2.9.2, 2.10.0-M3 y 2.10.0-SNAPSHOT (2.10.0-20120507-163905-843ac9520c) se produjo el mismo error

+0

Y quiero saber que este problema se registró en https://issues.scala-lang.org/ si esto es un error. –

Respuesta

6

Es un poco complicado. Es un error, el compilador de Scala debería emitir un error, pero es algo sutil.

El problema es que debido a que ha dejado public fuera del método abstracto, su visibilidad es de paquete privado. Si se escribe esto en Java:

package javapkgimpl; 

public class JavaClassImpl extends javapkg.JavaClass { 
    String foo(int b) { return (new java.lang.Integer(b)).toString(); } 
    public static void main(String[] args) { 
    System.out.println(new JavaClassImpl().bar(10)); 
    } 
} 

entonces el compilador de Java se quejará:

JavaClassImpl.java:3: javapkgimpl.JavaClassImpl is not abstract and does not 
    override abstract method foo(int) in javapkg.JavaClass 
public class JavaClassImpl extends javapkg.JavaClass { 
    ^
1 error 

Es claramente tratando para anular, pero en realidad no funciona, ya que no está en la derecha paquete y, por lo tanto, no puede acceder (o anular) el original foo. Si cambiamos el paquete a javapkg, entonces todo funciona. Si probamos este Scala en su lugar:

package javapkg 

class ScalaClass extends JavaClass{ 
    def foo(a:Int) = a.toString 
} 

object ScalaClass extends App{ 
    println(new ScalaClass().bar(10)) 
} 

entonces Scala funciona bien también.

Es culpa del compilador de Scala que no advierta este error, debería emitir el mismo error que el compilador de Java (o uno más útil que realmente le dice que el acceso es complicado) en lugar de emitiendo bytecode que no puede funcionar.

Pero es fácil de arreglar: simplemente cambie el paquete en el código de Scala (o el modificador de acceso en el código de Java).

+0

¡Buena respuesta! (llenar) – Luciano

Cuestiones relacionadas