2010-05-26 16 views
12

मैं जानना चाहता हूं कि केस कक्षाओं की प्रति विधि को सारणी बनाना संभव है या नहीं। असल में मेरे पास sealed trait Op और कुछ case class Push(value: Int) extends Op और case class Pop() extends Op जैसे कुछ है।केस क्लास कॉपी() विधि abstraction

पहली समस्या: बिना तर्क/सदस्यों के केस केस एक प्रति विधि परिभाषित नहीं करता है। आप आरईपीएल में कोशिश कर सकते हैं।

scala> case class Foo() 
defined class Foo 

scala> Foo().copy() 
<console>:8: error: value copy is not a member of Foo 
     Foo().copy() 
      ^

scala> case class Foo(x: Int) 
defined class Foo 

scala> Foo(0).copy() 
res1: Foo = Foo(0) 

क्या कोई कारण है कि संकलक इस अपवाद को बनाता है? मुझे लगता है कि यह अपेक्षाकृत असंभव है और मैं प्रत्येक केस क्लास की प्रतिलिपि विधि को परिभाषित करने की अपेक्षा करता हूं।

दूसरी समस्या: मेरे पास एक विधि def ops: List[Op] है और मैं ops map { _.copy() } जैसे सभी ऑप्स कॉपी करना चाहता हूं। मैं Op विशेषता में प्रतिलिपि विधि को कैसे परिभाषित करूं? अगर मैं def copy(): Op कहता हूं तो मुझे "बहुत अधिक तर्क" त्रुटि मिलती है। हालांकि, चूंकि सभी प्रतिलिपि() विधियों में केवल वैकल्पिक तर्क हैं: यह गलत क्यों है? और, मैं यह कैसे सही करूं? def clone(): Op नामक एक और विधि बनाकर और सभी केस कक्षाओं के लिए def clone() = copy() लिखें? मुझे आशा नहीं है।

+1

आपके प्रश्न का उत्तर, "केस वर्गों की प्रति विधि को सारणी बनाना संभव है", आपके प्रश्न के अन्य पहलुओं को अनदेखा करना है: हां। आप लेंस नामक अवधारणा को देखना चाहते हैं। स्कैला और स्कालाज़ में लेंस पर एडवर्ड Kmett द्वारा एक शानदार वीडियो है एक पुस्तकालय है जो उन्हें एक बहुत समृद्ध पुस्तकालय के रूप में लागू करता है। एक कंपाइलर प्लगइन (लेंस) भी है जो इसे हस्तलेखन के बजाय आवश्यक बॉयलरप्लेट उत्पन्न करता है। उम्मीद है कि scalamacros.org जल्द ही इसे कम कर देगा। –

उत्तर

9
  1. किसी भी तर्क के बिना कक्षा कक्षाओं के लिए एक कंपाइलर जेनरेट की गई प्रति विधि का लाभ क्या होगा? यह सिर्फ एक नया फू वापस करेगा, और कुछ भी कॉपी नहीं करेगा।
  2. quote Lukas Rytz करने के लिए (मेरा मानना ​​है कि वह इसे लागू):
अगर कोई सदस्य "कॉपी" वर्ग में नामित किया गया है प्रतिलिपि तरीकों केवल उत्पन्न कर रहे हैं, सीधे परिभाषित या विरासत में मिला।
+16

बेनिफिट स्पष्ट रूप से स्थिरता होगी। –

+1

ठीक है, मैं सहमत हूं। लेकिन इसमें कई लाभ नहीं होंगे क्योंकि आप प्रतिलिपि विधि पर वास्तव में सार नहीं लगा सकते हैं। –

+0

और फिर आप केस क्लास के विभिन्न उदाहरणों को गैर-मानित समेकित प्रकार के रूप में उपयोग कर सकते हैं। –

1

आपको अपने केस क्लास उदाहरणों की समान प्रतियां बनाने की आवश्यकता क्यों है? केस क्लास डिफ़ॉल्ट रूप से अपरिवर्तनीय हैं, इसलिए सुरक्षित रूप से साझा किया जा सकता है।

किसी भी मामले में, मुझे नहीं लगता है कि तुम क्या आप डिफ़ॉल्ट पैरामीटर के साथ पूछ रहे हैं क्या कर सकते हैं करते हैं:

scala> trait Op { def copy():Op }   
defined trait Op 

scala> case class Op1(v:Int) extends Op  
<console>:6: error: class Op1 needs to be abstract, since method copy in trait Op of type()Op is not defined 
     case class Op1(v:Int) extends Op 

संकलक को परिभाषित कक्षा में वैकल्पिक पैरामीटर के सभी संयोजनों के साथ तरीकों का निर्माण नहीं करता । डिफ़ॉल्ट मान उस स्थान पर डाले जाते हैं जहां विधि कहा जाता है।

+0

क्योंकि मुझे उदाहरण के अनुसार बनाई गई वस्तुओं को संदर्भित करने की आवश्यकता है और मूल्य से नहीं। इसे साझा करने या एक परिवर्तनीय/अपरिवर्तनीय चर्चा के साथ कुछ भी करने की ज़रूरत नहीं है। वैसे: आपने एक प्रश्न पोस्ट किया, जवाब नहीं। –

+0

यदि आपको मूल्य अर्थशास्त्र की आवश्यकता नहीं है, तो आप केस क्लास का उपयोग क्यों कर रहे हैं? उदाहरण के लिए –

+0

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

1

उपरोक्त बेन का जवाब। लेकिन क्या होगा अगर आप कुछ इस तरह करना चाहता था:

sealed trait Op 
case class Push(value: Int, context:String) extends Op 
case class Pop(context:String) extends Op 

val stackOps = List(Push(3, "foo"), Pop("foo")) 

def copyToContext(newContext:String, ops:List[Op]): List[Op] = { 
    // ... ? 
} 

val changedOps = copyToContext("bar", stackOps) 

// would return: List(Push(3, "bar"), Pop("bar")) 
12

आप clone साथ भ्रमित copy होने लगते हैं। copy का लक्ष्य लगभग समान प्रतिलिपि बनाने के लिए है, लेकिन कुछ बदल गया है। कुछ ऐसा हो सकता है जो केस क्लास के पैरामीटर पर निर्भर करता है, इसलिए इसे एक सामान्य विधि बनाना संभव नहीं है।

case class X() के मामले में, यह copy विधि के लिए बहुत अधिक समझ में नहीं आता है, क्योंकि वहां कुछ भी नहीं बदला जा सकता है।

दूसरी तरफ, clone एक जावा विधि है जिसका लक्ष्य किसी ऑब्जेक्ट की सही प्रतियां उत्पन्न करना है, जो आपको लगता है कि ऐसा लगता है।

+0

उचित रूप से उपयोग किया जाता है (कोई व्यवहार्य स्थिति नहीं है), किसी भी गुण के साथ केस कक्षाओं को कोई समझ नहीं आता है, क्योंकि प्रत्येक उदाहरण हर दूसरे उदाहरण से अलग नहीं है। –

+1

मैं सहमत नहीं हूं। क्लोन केस वर्गों के लिए उत्पन्न नहीं होता है लेकिन प्रतिलिपि है। और डिफ़ॉल्ट रूप से केस कक्षाओं के लिए क्लोन पहुंच योग्य नहीं है। इस सवाल के साथ मेरा इरादा एक प्रतिलिपि पाने और नरसंहार पेस्ट करना था। गति महत्वपूर्ण है इसलिए खेल से संबंधित संबंध हैं। परिणाम? मैंने लिखा है "ओवरराइड डीफ़ क्लोन() = कॉपी()" और "150+ केस क्लास में डीफ़ क्लोन() = केस क्लास()" ओवरराइड करें। आईएमएचओ यह इष्टतम से बहुत दूर है और इसे बहुत आसान किया जा सकता था। –

+1

@ जोआ लेकिन यदि किसी केस क्लास में कोई पैरामीटर नहीं है, तो इसमें प्रत्येक ऑब्जेक्ट अन्य सभी के बराबर है। आंतरिक वर्रों और vals के अलावा, जिन्हें किसी भी तरह 'प्रतिलिपि' द्वारा कॉपी नहीं किया गया है। –

2

जैसा कि मिर्को सही ढंग से इंगित करता है, आप कॉपी विधि पर वास्तव में अमूर्त नहीं हो सकते हैं। मैं डैनियल के विचार का समर्थन करता हूं, जो क्लोनिंग आप चाहते हैं, हालांकि मैं बॉयलरप्लेट को कम करने के लिए इसे कुछ सहायक कोड से लपेटूंगा।

आप प्रतिलिपि कार्यशीलता के साथ एक mixin विशेषता परिभाषित कर सकते हैं और बस उसके बाद अपने मामले वर्गों में यह मिश्रण: बजाय

trait ClonableAs[T] extends Cloneable { this: T => 
    def makeClone() = super.clone().asInstanceOf[T] 
} 

case class Foo(i: Int) extends ClonableAs[Foo] 

List(Foo(1), Foo(2), Foo(3)).map(_.makeClone()) 

इस तरह अपने मामले वर्गों में से प्रत्येक के लिए एक समान विधि जोड़ने के लिए, आप उन्हें विस्तार करना सहायक विशेषता, जो उन्हें क्लीनर बनाती है और आपको कुछ कीस्ट्रोक बचाती है।

दूसरी ओर, क्लोनिंग अपरिवर्तनीय वस्तुओं के लिए कोई समझ नहीं लेता है, इसलिए मैं अनुमान लगाता हूं कि आपके वर्गों में उत्परिवर्तनीय स्थिति है। मैं आपको पुनर्विचार करने की सलाह दूंगा यदि आप वास्तव में उन्हें अपरिवर्तनीय नहीं बना सकते हैं, और अंतिम उपाय पर केवल उस प्रकार के क्लोनिंग का उपयोग करें। अपरिवर्तनीयता त्रुटियों की कक्षा से खुद को सुरक्षित रखेगी।

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