8

以下のコードを実行すると、AbstractMethodError が発生することに気付きました。

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)

これはバグですか、それとも仕様ですか?

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

4

2 に答える 2

8

少し複雑です。これはバグです -- Scala コンパイラはエラーを出力するはずです -- しかし、やや微妙なバグです。

問題はpublic、抽象メソッドを省略したため、その可視性がパッケージ プライベートであることです。これを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 を試すと:

package javapkg

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

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

その後、Scalaも正常に動作します。

この間違いに気付かないのは Scala のコンパイラのせいです.Java コンパイラと同じエラーを出力するはずです.仕事。

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

于 2012-05-11T18:19:59.457 に答える