2012-05-11 6 views
6

次のコードを実行すると、AbstractMethodErrorが発生しました。Abstractプライベートメソッドのオーバーライド時にエラーが発生しました

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) 

これはバグか仕様か?

P.S. Scalaバージョン2.9.2、2.10.0-M3および2.10.0-SNAPSHOT(2.10.0-20120507-163905-843ac9520c)同じエラーが発生しました

+0

そして、私はこの問題がhttps://issues.scala-lang.org/に登録されていることを知りたいのですが、これはバグです。 –

答えて

6

これは少し複雑です。これはバグです。Scalaコンパイラはエラーを出すべきですが、やや微妙です。

publicを抽象メソッドから除外しているため、その可視性はpackage-privateです。あなたは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)); 
    } 
} 

その後、Javaコンパイラは文句を言うだろう:

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 

をそれは明確に上書きするをしようとですが、それは右ではないので、それは実際には動作しません。したがって、元のfooに実際にアクセス(または上書き)することはできません。パッケージをjavapkgに変更すると、すべて正常に動作します。代わりにScalaを試してみると、Scalaはうまく動作します。

package javapkg 

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

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

Scalaのコンパイラでは、このミスに気付かないことがあります。これは、Javaコンパイラと同じエラーを出す必要があります(または、実際にあなたがアクセスが難しいと伝えるより有用なものです)。動作しないバイトコードを放出する。

しかし、修正するのは簡単です。パッケージをScalaコード(またはJavaコードのアクセス修飾子)で変更するだけです。

+0

ニースの答え! (塗りつぶし) – Luciano

関連する問題