2012-05-11 21 views
6

Tôi nhận thấy rằng AbstractMethodError xảy ra khi thực thi các mã sau đây.AbstractMethodError xảy ra khi gói phương thức riêng tư ghi đè

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) 

Đây có phải là một lỗi hoặc đặc điểm kỹ thuật?

P.S. Phiên bản Scala 2.9.2, 2.10.0-M3 và 2.10.0-SNAPSHOT (2.10.0-20120507-163905-843ac9520c) xảy ra lỗi tương tự

+0

Và tôi muốn biết vấn đề này đã được đăng ký với https://issues.scala-lang.org/ nếu đây là lỗi. –

Trả lời

6

Đó là một chút phức tạp. Đó là một lỗi - trình biên dịch Scala sẽ phát ra một lỗi - nhưng đó là một lỗi nhỏ.

Vấn đề là do bạn đã rời khỏi phương pháp trừu tượng public, khả năng hiển thị của nó là gói riêng tư. Nếu bạn viết những dòng này trong 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)); 
    } 
} 

sau đó trình biên dịch Java sẽ phàn nàn:

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 

Nó rõ ràng là cố gắng để ghi đè lên, nhưng nó không thực sự làm việc kể từ khi nó không phải là ở bên phải và do đó không thể truy cập (hoặc ghi đè) bản gốc foo. Nếu chúng tôi thay đổi gói thành javapkg thì mọi thứ sẽ hoạt động. Nếu chúng ta cố gắng Scala này thay vì:

package javapkg 

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

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

sau đó Scala hoạt động tốt cũng có.

Đó là lỗi của trình biên dịch của Scala mà nó không nhận thấy lỗi này - nó sẽ phát ra lỗi giống như trình biên dịch Java (hoặc trình biên dịch hữu ích hơn thực sự cho bạn biết rằng truy cập không đúng)! phát ra bytecode không thể hoạt động.

Nhưng thật dễ dàng để sửa lỗi: chỉ cần thay đổi gói trên mã Scala (hoặc bộ sửa đổi truy cập trong mã Java).

+0

Câu trả lời hay! (lấp đầy) – Luciano

Các vấn đề liên quan