2012-01-12 8 views
5

मेरे मन में निम्नलिखित वर्ग है रिटर्न:स्काला सार वर्ग विधि है कि एक नए इसी वर्ग बच्चे वस्तु

abstract class MyClass (data: MyData) { 

    def update(): MyClass = { 
    new MyClass(process()) 
    } 

    def process(): MyData = { 
    ... 
    } 

} 

हालांकि, सार वर्गों instantiated नहीं किया जा सकता है, ताकि लाइन new MyClass(process()) कोई त्रुटि है। मेरा सवाल है - क्या संकलक को बताने का कोई तरीका है कि MyClass के प्रत्येक बच्चे वर्ग के मामले में मैं बिल्कुल उस बच्चे वर्ग का ऑब्जेक्ट बनाना चाहता हूं? यह सभी बाल वर्गों में इस विधि को लिखने के लिए एक ओवरकिल लगता है। कक्षा या विधि के प्रकार पैरामीटर के साथ खेलना मैं खुद को स्वीकार नहीं कर सका।

+0

(सुनिश्चित नहीं है कि यह आपके उपयोग के मामले में फिट होगा या नहीं) क्या आपने केस क्लास पर एक नज़र डाली और उन्हें कॉपी कैसे किया? ... वैसे भी अगर आप वास्तव में ऐसा करना चाहते हैं, तो आप टाइप एरर के खिलाफ लड़ेंगे। –

उत्तर

6

इस तरह कुछ कैसे? MyClass कंक्रीट प्रकार के साथ parametrized है। बेशक, सभी ठोस वर्गों को एक विधि को लागू करना होता है जो वास्तव में Self का एक नया उदाहरण देता है।

trait MyClass[+Self <: MyClass[Self]] { 
    def update(): Self = { 
    makeNew(process()) 
    } 

    def process(): MyData = { 
    // ... 
    } 

    protected def makeNew(data: MyData): Self 
} 

class Concrete0 extends MyClass[Concrete0] { 
    protected def makeNew(data: MyData) = new Concrete0 
} 

class RefinedConcrete0 extends Concrete0 with MyClass[RefinedConcrete0] { 
    override protected def makeNew(data: MyData) = new RefinedConcrete0 
} 

क्रेडिट: IttayD’s second update to his answerthis question करने के लिए।

3

सभी उप-वर्गों में लगभग समान विधि को लागू करने से पूरी तरह से बचने के लिए आपको प्रतिबिंब का उपयोग करने की आवश्यकता होगी। मुझे लगता है कि अगर आपने स्काला चुना है तो आपका आखिरी उपाय होगा।

// additional parameter: a factory function 
abstract class MyClass(data: MyData, makeNew: MyData => MyClass) { 

    def update(): MyClass = { 
    makeNew(process()) 
    } 
    def process(): MyData = { 
    ... 
    } 
} 

class Concrete(data: MyData) extends MyClass(data, new Concrete(_)) 

इस तरह आप केवल सबसे छोटा टुकड़ा उपवर्ग का दृष्टांत के लिए आवश्यक दोहराने: तो यहाँ कैसे दोहराव कोड को कम करना है।

+0

लेकिन अब आपके ऑब्जेक्ट्स के प्रत्येक उदाहरण में एक अतिरिक्त फ़ील्ड है, जबकि इसे एक अमूर्त विधि के रूप में परिभाषित किया जा सकता है, फ़ील्ड को सहेजना (थोड़ा और टाइपिंग के लिए)। –

+0

सच है, हालांकि यह एक व्यापार-बंद है, क्योंकि सभी को लिखना पसंद नहीं है "संरक्षित डीफ मेक्यू (डेटा: माईडाटा) = नया कंक्रीट (डेटा)" प्रत्येक सबक्लास में –