2012-05-11 13 views
6

ओवरराइड करता है मैंने देखा कि निम्न कोड निष्पादित करते समय 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) 

यह एक बग या विनिर्देश है?

पीएस स्कैला संस्करण 2.9.2, 2.10.0-एम 3 और 2.10.0-स्नैपशॉट (2.10.0-20120507-163905-843ac9520c) एक ही त्रुटि हुई

+0

और मैं जानना चाहता हूं कि यह समस्या https://issues.scala-lang.org/ पर पंजीकृत है यदि यह बग है। –

उत्तर

6

यह थोड़ा जटिल है। यह एक बग है - स्कैला कंपाइलर को एक त्रुटि उत्सर्जित करनी चाहिए - लेकिन यह कुछ हद तक सूक्ष्म है।

समस्या यह है कि चूंकि आपने अमूर्त विधि से public छोड़ा है, इसकी दृश्यता पैकेज-निजी है। आप जावा में इस लिखते हैं:

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

तो जावा कम्पाइलर शिकायत:

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 पर बदलते हैं, तो सब कुछ काम करता है। यदि हम इसके बजाय इस स्कैला को आजमाते हैं:

package javapkg 

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

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

तब स्कैला भी ठीक काम करता है।

स्कैला के कंपाइलर की यह गलती है कि यह इस गलती को नहीं देखती है - इसे जावा कंपाइलर के रूप में एक ही त्रुटि को छोड़ना चाहिए (या एक और सहायक जो वास्तव में आपको बताता है कि पहुंच खराब है!) बाइटकोड उत्सर्जित करना जो काम नहीं कर सकता है।

लेकिन यह ठीक करना आसान है: केवल स्कैला कोड (या जावा कोड में एक्सेस संशोधक) पर पैकेज बदलें।

+0

अच्छा जवाब! (भरने) – Luciano

संबंधित मुद्दे