2013-07-09 6 views
7

एक परिवर्तनशील वस्तु के साथ मैं की तरहस्काला "अद्यतन" अपरिवर्तनीय वस्तु सर्वोत्तम प्रथाओं

var user = DAO.getUser(id) 
user.name = "John" 
user.email ="[email protected]" 
// logic on user 

कुछ लिख सकते हैं तो उपयोगकर्ता तो मैं \ हर बदलाव संचालन पर इसे कॉपी क्लोन करने के लिए की जरूरत है अपरिवर्तनीय है।

मैं इस

  1. मामले वर्ग प्रति
  2. विधि (changeName) की तरह है कि नए संपत्ति

सर्वोत्तम तरीका क्या है के साथ एक नई वस्तु बनाता है प्रदर्शन करने के लिए कुछ तरीके पता है?

और एक और सवाल। क्या मूल वस्तु से संबंधित "परिवर्तन" प्राप्त करने के लिए कोई मौजूदा तकनीक है (उदाहरण के लिए अद्यतन कथन उत्पन्न करने के लिए)?

+0

परिवर्तन पाने के लिए आपको इवेंट सोर्सिंग इस्तेमाल कर सकते हैं। –

उत्तर

8

आपके द्वारा वर्णित दोनों तरीकों क्रमशः कार्यात्मक और ओओ प्रतिमानों से संबंधित हैं। यदि आप अमूर्त डेटा प्रकार के साथ कार्यात्मक अपघटन पसंद करते हैं, जो स्कैला में केस वर्गों द्वारा दर्शाया जाता है, तो प्रतिलिपि विधि चुनें। म्यूटेटर का उपयोग करना मेरे विकल्प में एक अच्छा अभ्यास नहीं है, क्योंकि यह आपको जावा/सी #/सी ++ जीवन के रास्ते पर वापस खींच देगा।

case class Person(name: String, age: String) 

दूसरी ओर एडीटी मामले वर्ग बनाने पर

की तरह तो अधिक consise है:

class Person(_name: String, _age: String) { 
    var name = _name 
    var age = _a 

    def changeName(newName: String): Unit = { name = newName } 
    // ... and so on 
} 

(नहीं सबसे अच्छा जरूरी कोड, कम हो सकता है, लेकिन स्पष्ट)।

कारण के

mutators साथ एक और तरीका है, बस प्रत्येक कॉल पर एक नई वस्तु वापस जाने के लिए:

class Person(val name: String, 
      val age: String) {  
    def changeName(newName: String): Unit = new Person(newName, age) 
    // ... and so on 
} 

लेकिन फिर भी मामले वर्ग तरह से अधिक consise है।

और यदि आप समवर्ती/समांतर प्रोग्रामिंग के लिए फ़्यूचर जाते हैं, तो आप देखेंगे कि अपरिवर्तनीय मान के साथ कार्यशील पूर्ण कार्य बेहतर है, फिर अनुमान लगाने के लिए कि वर्तमान में आपका ऑब्जेक्ट किस स्थिति में है।

अद्यतन

Senia के लिए धन्यवाद, दो बातें उल्लेख करना भूल गया।

लेंस
सबसे बुनियादी स्तर पर, लेंस getters और अपरिवर्तनीय डेटा के लिए setters की तरह कर रहे हैं और इस तरह दिखता है:

case class Lens[A,B](get: A => B, set: (A,B) => A) { 
    def apply(a: A) = get(a) 
    // ... 
} 

यह है कि। एक लेंस एक वस्तु है जिसमें दो कार्य होते हैं: प्राप्त करें और सेट करें। ए लेता है और एक बी सेट देता है ए और बी लेता है और एक नया ए देता है। यह देखना आसान है कि प्रकार बी ए में निहित एक मान है। जब हम एक उदाहरण पास करते हैं तो हम उस मान को वापस कर देते हैं। जब हम सेट करने के लिए ए और ए पास करते हैं तो हम ए में मान बी अपडेट करते हैं और परिवर्तन को प्रतिबिंबित करते हुए एक नया ए वापस कर देते हैं। सुविधा के लिए प्राप्त करने के लिए प्राप्त किया गया है।वहाँ Scalaz लेंस मामले वर्ग

रिकॉर्ड्स
यह एक, ofcause, shapeless पुस्तकालय और कहा जाता रिकॉर्ड्स से आता है के लिए एक अच्छा intro है। एसोसिएशन के एचएलिस्ट के रूप में मॉडलिंग किए गए एक्स्टेंसिबल रिकॉर्ड्स का कार्यान्वयन। कुंजी सिंगलटन प्रकार का उपयोग कर इनकोड और पूरी तरह से उनके संबंधित मान के प्रकार (GitHub से पूर्व) का निर्धारण:

object author extends Field[String] 
object title extends Field[String] 
object price extends Field[Double] 
object inPrint extends Field[Boolean] 

val book = 
    (author -> "Benjamin Pierce") :: 
    (title -> "Types and Programming Languages") :: 
    (price -> 44.11) :: 
    HNil 

// Read price field 
val currentPrice = book.get(price) // Inferred type is Double 
currentPrice == 44.11 

// Update price field, relying on static type of currentPrice 
val updated = book + (price -> (currentPrice+2.0)) 

// Add a new field 
val extended = updated + (inPrint -> true) 
+3

आप अपने उत्तर में तीसरा रास्ता जोड़ सकते हैं: [लेंस] (https://blog.stackmob.com/2012/02/an-introduction-to-lenses-in-scalaz/)। यह नए उत्तर के लिए पर्याप्त नहीं है, लेकिन यह उल्लेख करने लायक है। – senia

+0

@senia धन्यवाद लेंस और आकारहीन रिकॉर्ड जोड़ा गया – 4lex1v

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