2016-02-16 5 views
6

के भीतर सामान्य संपत्ति को ओवरराइड करें, मैं कुछ सामान्य कोड लिखने की कोशिश कर रहा हूं, लेकिन Type of 'PROPERTY' is not a subtype of the overridden property त्रुटि से छुटकारा नहीं पा सकता। मेरी कोड केकोटलिन: सबटाइप

सरलीकृत संस्करण:

abstract class BaseP<V> { 
    var view: V? = null 
} 

abstract class BaseF { 
    fun smth() { 
     pp.view = this 
    } 
    abstract val pp: BaseP<BaseF> 
} 

abstract class SubF: BaseF() { 
    abstract override val pp: BaseP<SubF> 
    // Error:(20, 30) Type of 'pp' is not a subtype of the overridden property 'public abstract val pp: BaseP<BaseF> defined in BaseF' 
} 

मैंने पाया कि त्रुटि @Suppress एड हो सकता है लेकिन मुझे शक है यह सबसे अच्छा और एक ही रास्ता है। क्या कुछ बेहतर है?

और आखिरकार मैं समझ नहीं पा रहा हूं, क्यों subtypeA<subtypeB>baseA<baseB> के उप प्रकार के रूप में नहीं गिना जाता है, क्या कोई इसे समझा सकता है?

+0

क्या लाइन त्रुटि को फेंकता है? – voddan

उत्तर

7

पहला, SubtypeA<B>BaseA<B> का उप प्रकार है, इसलिए समस्या जेनेरिक पैरामीटर उप-टाइपिंग में है।

उत्तर Kotlin generics variance में है, जो that of Java के समान है।

SubtypeA<SubtypeB>BaseA<BaseB> के उप प्रकार के रूप में क्यों नहीं गिना जाता है?

जेनरिक डिफ़ॉल्ट, जिसका मतलब है कि, भी सरल मामले में, एक वर्ग के लिए A<T>, A<SubtypeB> और A<BaseB> नहीं एक दूसरे के उपप्रकार जब तक अन्यथा विचरण संशोधक द्वारा निर्दिष्ट किया जाता हैं in और out (या Java wildcards) द्वारा अपरिवर्तनीय हैं ।

दो मामलों में संभव हो रहे हैं:

  • यदि आप चाहते हैं अपनी कक्षा A के उदाहरण से बाहरT उदाहरणों ले केवल करने के लिए है, तो आप out संशोधक का उपयोग कर सकते हैं: A<out T>

    यहाँ A<SubtypeB>, A<BaseB> की एक उप-प्रकार हो जाता है क्योंकि A<SubtypeB> से आपको स्पष्ट रूप से BaseB के उदाहरण ले जा सकते हैं, और इसके नहीं विपरीत। A<in T>:

  • आप केवल पास करने के लिएT अपने वर्ग 'के तरीकों में है, तो अपने वर्ग घोषणा में in संशोधक का उपयोग करना चाहते हैं। क्योंकि A<BaseB> के प्रत्येक उदाहरण भी तरीकों में SubtypeB प्राप्त कर सकते हैं, लेकिन इसके विपरीत नहीं

    और यहाँ A<BaseB>, A<SubtypeB> की एक उप-प्रकार है।

तुम दोनों गुजरती हैं और करने के लिए/T ले अपनी कक्षा A<T> से है, तो T के लिए एकमात्र विकल्प यह अपरिवर्तनीय होने के लिए इतना है कि न तो A<SubB> है और न ही A<SuperB>A<B> के उपप्रकार हैं: अन्यथा एक विरोधाभास का नेतृत्व करेंगे उपरोक्त के लिए।

और यह वास्तव में मामला है: अपने BaseP<B>, आप दोनों V के आइटम ले जा रहे हैं और view संपत्ति में लोगों को डाल में है, इसलिए केवल V अपरिवर्तनीय हो सकता है, और BaseP<SubF>BaseP<BaseF> की एक उप प्रकार नहीं है, न तो SubP<SubF> है।