2015-06-17 15 views
7

मैं कोटलिन में आंशिक प्रतिनिधि तरीकों/फ़ील्ड कैसे कर सकता हूं?कोटलिन में आंशिक वर्ग प्रतिनिधिमंडल

विशिष्ट होना करने के लिए: यहाँ मैं इंटरफ़ेस TraitA से वर्ग User वारिस और आवरण StateA में क्षेत्र marked: Boolean लागू करने के लिए कोशिश कर रहा हूँ। इससे User कार्यान्वयन को साफ कर दिया जाएगा, क्योंकि marked केवल एक राज्य क्षेत्र है। ध्यान दें कि TraitA एक वर्ग नहीं किया जा सकता क्योंकि मैं कई तरह के इंटरफेस का उपयोग करना चाहते: User() : TraitA by StateA, TraitB by StateB, ..

/* does not compile (Kotlin M12) */ 
interface TraitA { 
    var marked: Boolean 

    fun doStaffWithMarked() // must be overridable 
} 

class StateA() : TraitA { 
    override var marked = false 
} 

class User() : TraitA by StateA(){ 
    override fum doStaffWithMarked() { 
     //...all fancy logic here... 
    } 
} 

विकल्प एक ही स्थान पर सभी को लागू करना है:

class User() : TraitA{ 
    override var marked = false // ugly code 

    override fum doStaffWithMarked() { 
     //... 
    } 
} 

वहाँ एक रास्ता/पैटर्न है कि उस समस्या को आसानी से और जितना संभव हो उतना छोटा कोड हल करेगा? कोड/बाइटकोड पीढ़ी मेरे लिए एक विकल्प नहीं है।

अद्यतन

मुझे लगता है कि बारे में बहुत स्पष्ट नहीं था, लेकिन कृपया ध्यान दें कि doStaffWithMarked()अद्वितीय हर User के लिए है।

तो मैं एक 'आधा बुरा' रन-टाइम वक्तव्य दिये समाधान का सुझाव हो सकता है:

interface TraitA { 
    var marked: Boolean 

    /* must be overridden */ 
    fun doStaffWithMarked() = throw UnsupportedOperationException() 
} 

class StateA() : TraitA { 
    override var marked = false 
} 

class User() : TraitA by StateA() { 
    override fum doStaffWithMarked() { 
     //...all fancy logic here... 
    } 
} 

सवाल है, अभी भी खुला है के बाद से एक बहुत अच्छी समाधान की जाँच करेगा कि doStaffWithMarked() संकलन समय में।

+0

isMarked() में TraitA लगता है अनावश्यक। आप बस इसके रूप में चिह्नित कर सकते हैं। –

+0

'isMarked()' बहुत सारे फैंसी स्टाफ करता है और प्रत्येक अंतिम उपयोगकर्ता – voddan

+0

के लिए अतिसंवेदनशील होना चाहिए, मुझे नहीं लगता कि यह जल्द से जल्द संभव होगा, क्योंकि स्टेटए वास्तव में एक पूर्ण श्रेणी नहीं है, आप इसे DoStaffWithMarked के कार्यान्वयन के बिना तत्काल नहीं कर सकते हैं (), इसलिए स्टेटए अपने आप पर बेकार है। और उपयोगकर्ता जैसे कुछ वर्ग हैं जो एक पूर्ण वर्ग और राज्य ए है जो अधूरा वर्ग है, बहुत अजीब है और मुझे लगता है कि – D3xter

उत्तर

7

स्प्लिट तक TraitA दो इंटरफेस में, फिर एक प्रतिनिधि और अन्य लागू:

interface TraitA { 
    var marked: Boolean 
} 

interface TraitAPlus : TraitA { 
    fun isMarked(): Boolean 
} 

class StateA() : TraitA { 
    override var marked = false 
} 

class User() : TraitA by StateA(), TraitAPlus { 
    override fun isMarked(): Boolean { 
     return marked 
    } 
} 
+1

भाषा स्तर पर ऐसे पैटर्न का समर्थन करने के लिए अच्छा होगा। यकीन नहीं है कि यह कैसा दिखता है, यद्यपि। – voddan

+1

कोटलिन का आदर्श वाक्य चीजों को स्पष्ट कर रहा है। मुझे लगता है कि संकलक आपको अधूरे कार्यान्वयन के लिए इंटरफेस का प्रतिनिधि बनने की अनुमति दे सकता है लेकिन यह समाधान यह स्पष्ट करता है कि प्रतिनिधि क्या है और क्या लागू किया गया है। –

1

यहाँ एक संस्करण है कि बस सौंपने के बजाय StateA से inherites है, लेकिन है कि बहुत अच्छा नहीं है:

interface TraitA { 
    var marked: Boolean 

    fun isMarked(): Boolean 
} 

abstract class StateA() : TraitA { 
    override var marked = false 
} 

class User() : TraitA, StateA() { 
    override fun isMarked(): Boolean { 
     return marked 
    } 
} 

और यहाँ कुछ हद तक एक unusal दृष्टिकोण जहाँ मैं StateA

class User() : TraitA by object : StateA() { 
    override fun isMarked(): Boolean { 
     return marked 
    } 
} { 

} 
की एक अनाम उदाहरण के लिए TraitA प्रतिनिधि है

यद्यपि ईमानदार होने के लिए, मैं बजाय कक्षा पदानुक्रम के डिजाइन पर पुनर्विचार करना चाहता हूं। विशेष रूप से, आप इंटरफ़ेस में विधि कार्यान्वयन (लेकिन संपत्ति मान नहीं) डाल सकते हैं, इसलिए isMarked() केवल marked पर निर्भर करता है, तो आप इसे सीधे TraitA में कार्यान्वित कर सकते हैं। आपका कोड तो हो जाता है:

interface TraitA { 
    var marked: Boolean 

    fun isMarked(): Boolean { 
     return marked 
    } 
} 

class StateA() : TraitA { 
    override var marked = false 
} 

class User() : TraitA by StateA() { 

} 

संपादित करें: अलग जवाब: https://stackoverflow.com/a/30914383/615306

+1

उत्तर के लिए धन्यवाद।लेकिन जैसा कि आपने कहा था, वे दृष्टिकोण बहुत अच्छे नहीं हैं। आखिरी बात यह नहीं है कि मुझे 'मार्कमार्क()' अतिरंजित होना चाहिए (अपडेट देखें)। कक्षाओं के साथ पहला व्यक्ति बहु-विरासत के पूरे विचार को मारता है। अनाम वस्तुओं के साथ दूसरा काम करता है, लेकिन यह * रात्रिभोज * बदसूरत है। – voddan

+1

मैं सहमत हूं। क्या आप ट्रेटा को दो इंटरफेस में विभाजित कर सकते हैं, ताकि आप उनमें से एक को प्रतिनिधि बना सकें और दूसरे को कार्यान्वित कर सकें? मेरा संपादन देखें। –

+1

बिंगो! यह काम करता है, और मैं इसे स्केल करने में सक्षम हूं: http://try.kotlinlang.org/#/UserProjects/oofhklfiv3hi54r971le3l1tth/7pc2m0b7nnkpg766kplfhq3m9v – voddan

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