टाइप क्लास पैटर्न का उपयोग करने वाली स्कैला प्रोजेक्ट पर काम करते समय, मैं इस बात को लेकर गंभीर समस्या में प्रतीत होता हूं कि भाषा पैटर्न को कैसे लागू करती है: चूंकि स्कैला प्रकार-श्रेणी कार्यान्वयन का प्रबंधन किया जाना चाहिए प्रोग्रामर और भाषा नहीं, किसी भी प्रकार के वर्ग से संबंधित किसी भी चर को कभी भी माता-पिता के रूप में एनोटेटेड नहीं किया जा सकता है जब तक कि इसके प्रकार-वर्ग कार्यान्वयन को इसके साथ नहीं लिया जाता है।स्कैला प्रकार कक्षाओं को सामान्यीकृत करने में समस्याएं
इस बिंदु को वर्णन करने के लिए, मैं एक त्वरित उदाहरण कार्यक्रम कोडित गए हैं। कल्पना कीजिए कि आप ऐसे कार्यक्रम को लिखने की कोशिश कर रहे थे जो एक कंपनी के लिए विभिन्न प्रकार के कर्मचारियों को संभाल सके और उनकी प्रगति पर रिपोर्ट प्रिंट कर सके। स्काला में टाइप श्रेणी के पैटर्न के साथ इस समस्या के समाधान के लिए, आप कुछ इस तरह की कोशिश कर सकते: कर्मचारियों की
abstract class Employee
class Packer(boxesPacked: Int, cratesPacked: Int) extends Employee
class Shipper(trucksShipped: Int) extends Employee
एक वर्ग पदानुक्रम मॉडलिंग विभिन्न प्रकार के काफी सरल। अब हम ReportMaker टाइप-क्लास को कार्यान्वित करते हैं।
trait ReportMaker[T] {
def printReport(t: T): Unit
}
implicit object PackerReportMaker extends ReportMaker[Packer] {
def printReport(p: Packer) { println(p.boxesPacked + p.cratesPacked) }
}
implicit object ShipperReportMaker extends ReportMaker[Shipper] {
def printReport(s: Shipper) { println(s.trucksShipped) }
}
सब कुछ ठीक है और अच्छा है कि, और अब हम है कि इस प्रकार दिखाई देंगे रोस्टर वर्ग के कुछ प्रकार लिख सकते हैं:
class Roster {
private var employees: List[Employee] = List()
def reportAndAdd[T <: Employee](e: T)(implicit rm: ReportMaker[T]) {
rm.printReport(e)
employees = employees :+ e
}
}
तो यह काम करता है। अब, हमारे टाइप-क्लास के लिए धन्यवाद, हम रिपोर्ट में एक पैकर या शिपर ऑब्जेक्ट पास कर सकते हैं और विधि जोड़ें, और यह रिपोर्ट प्रिंट करेगा और कर्मचारी को रोस्टर में जोड़ देगा। हालांकि, रोस्टर में प्रत्येक कर्मचारी की रिपोर्ट मुद्रित करने का प्रयास करने वाली एक विधि लिखना असंभव होगा, रिपोर्ट के लिए पारित आरएम ऑब्जेक्ट को स्पष्ट रूप से संग्रहीत किए बिना और जोड़ें!
पैटर्न, हास्केल और क्लोजर का समर्थन करने वाली दो अन्य भाषाएं इस समस्या को साझा नहीं करती हैं, क्योंकि वे इस समस्या से निपटते हैं। हास्केल डेटाटाइप से वैश्विक स्तर पर कार्यान्वयन के लिए मैपिंग स्टोर करता है, इसलिए यह हमेशा परिवर्तनीय 'साथ' होता है, और क्लोजर मूल रूप से वही काम करता है। यहां एक त्वरित उदाहरण दिया गया है जो क्लोजर में पूरी तरह से काम करता है।
(defprotocol Reporter
(report [this] "Produce a string report of the object."))
(defrecord Packer [boxes-packed crates-packed]
Reporter
(report [this] (str (+ (:boxes-packed this) (:crates-packed this)))))
(defrecord Shipper [trucks-shipped]
Reporter
(report [this] (str (:trucks-shipped this))))
(defn report-roster [roster]
(dorun (map #(println (report %)) roster)))
(def steve (Packer. 10 5))
(def billy (Shipper. 5))
(def roster [steve billy])
(report-roster roster)
अलावा प्रकार सूची में कर्मचारी सूची मोड़ के बजाय बुरा समाधान से [(कर्मचारी, ReportMaker [कर्मचारी]), स्काला इस समस्या को हल करने के लिए किसी भी तरह से की पेशकश करता है? और यदि नहीं, क्योंकि स्कैला पुस्तकालय टाइप-क्लासेस का व्यापक उपयोग करते हैं, इसलिए इसे क्यों संबोधित नहीं किया गया है?
यह अभी तक subtyping सब कुछ खिलवाड़ का एक और उदाहरण है। यदि आप उप-प्रकार के बजाए अपने कर्मचारी उप-वर्गों को रचनाकारों (हास्केल अर्थ में) के रूप में सोचते हैं, तो आप पाएंगे कि टाइप क्लास दृष्टिकोण अधिक आरामदायक है। –
मुझे यकीन नहीं है कि हास्केल इस समस्या को जिस तरह से सोचता है उसे हल करेगा। हास्केल का मानक सूची प्रकार विषम नहीं है, इसलिए सभी तत्वों में समान टाइपक्लास उदाहरण होगा। एक ही सूची में अलग-अलग प्रकार 'पैकर' और 'शिपर' डालने का विचार बस काम नहीं करेगा। –