2013-07-09 13 views
5

एक जावा पुस्तकालय वर्ग मैं उपयोग कर रहा हूँ वाणीकैसे कार्यान्वित करें "कार्यान्वयन प्रतिबंध: विशेषता ... संरक्षित विधि का उपयोग ... एक ठोस विशेषता विधि के अंदर।"

protected getPage(): Page { ... } 

अब मैं विशेषताएं है कि मैं अक्सर उपयोग को जोड़ने के लिए एक सहायक स्काला mixin बनाना चाहते हैं। मैं कक्षा का विस्तार नहीं करना चाहता, क्योंकि जावा क्लास में विभिन्न उप-वर्ग हैं जो मैं अलग-अलग स्थानों पर विस्तार करना चाहता हूं।

Implementation restriction: trait MyMixin accesses protected method getPage inside a concrete trait method.

वहाँ एक समाधान यह काम करने के लिए कैसे, मेरे उपवर्गों को प्रभावित किए बिना है: समस्या यह है कि अगर मैं अपने mixin trait में getPage() उपयोग करते हैं, मैं इस त्रुटि मिलती है? और यह प्रतिबंध क्यों है?


अब तक, मैं एक काम के आसपास के साथ आया था: मैं के रूप में

override def getPage(): Page = super.getPage(); 

यह काम करने लगता है विशेषता में विधि ओवरराइड, लेकिन मैं पूरी तरह से संतुष्ट नहीं हूँ। सौभाग्य से मुझे अपने उप-वर्गों में getPage() को ओवरराइड करने की आवश्यकता नहीं है, लेकिन यदि मुझे आवश्यकता है, तो मुझे एक ही विधि के दो ओवरराइड मिलेंगे और यह कार्य-कार्य काम नहीं करेगा।

उत्तर

8

समस्या यह है कि हालांकि विशेषता जावा क्लास को विस्तारित करती है, फिर भी कार्यान्वयन वास्तव में जावा क्लास को विस्तारित करने में कुछ नहीं है। B के लिए विचार करें

class A { def f = "foo" } 
trait T extends A { def g = f + "bar" } 
class B extends T { def h = g + "baz" } 

वास्तविक बाईटकोड में हम

public java.lang.String g(); 
    Code: 
    0: aload_0 
    1: invokestatic #17; //Method T$class.g:(LT;)Ljava/lang/String; 
    4: areturn 

देखना जो इसका मतलब है कि बस कुछ T$class कहा जाता है, जो यह पता चला है के लिए आगे

public abstract class T$class extends java.lang.Object{ 
public static java.lang.String g(T); 
    Code: 
    ... 

तो का मुख्य भाग है A के सबक्लास से कोड को कॉल नहीं किया जाता है।

अब, स्कैला के साथ कोई समस्या नहीं है क्योंकि यह बाइटकोड से protected ध्वज को छोड़ देता है। लेकिन Java लागू करता है कि केवल उप-वर्ग सुरक्षित विधियों को कॉल कर सकते हैं।

और इस प्रकार आपको समस्या है, और संदेश।

आप आसानी से इस समस्या को हल नहीं कर सकते हैं, हालांकि त्रुटि संदेश से पता चलता है क्या शायद सबसे अच्छा विकल्प है:

public class JavaProtected { 
    protected int getInt() { return 5; } 
} 

scala> trait T extends JavaProtected { def i = getInt } 
<console>:8: error: Implementation restriction: trait T accesses 
     protected method getInt inside a concrete trait method. 
    Add an accessor in a class extending class JavaProtected as a workaround. 

नोट अंतिम पंक्ति।

class WithAccessor extends JavaProtected { protected def myAccessor = getInt } 
trait T extends WithAccessor { def i = myAccessor } 

काम करता है।

+0

धन्यवाद, यही वह है जो मैं बचाना चाहता था, मेरे उप-वर्गों में एक्सेसर्स जोड़ना। लेकिन अब मैं समझता हूं कि यह क्यों संभव नहीं है। –

+0

@ PetrPudlák - आपको _every_ subclass में एक्सेसर्स जोड़ने की ज़रूरत नहीं है, केवल _one_ accessor-original के उप-वर्ग को सक्षम करने के लिए। फिर अन्य सभी जो विशेषता में मिश्रण करते हैं वे मूल के बजाय एक्सेसर-सक्षम वर्ग का विस्तार करेंगे। (बेशक, संरक्षित एक्सेसर्स इंटरफेस का हिस्सा होंगे, लेकिन कम से कम आपको केवल उन्हें एक बार लिखना होगा।) –

+0

समस्या यह है कि मैं जावा कक्षाओं के गुण में मिश्रण करना चाहता हूं जिसका एकमात्र आम सुपरक्लास है जावा पुस्तकालययही कारण है कि मैं विस्तारित जावा कक्षाओं के लिए स्कैला सबक्लास बनाने के बिना कार्यक्षमता जोड़ने के लिए, मिश्रण मिश्रण का उपयोग करना चाहता था। –

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