यह समझने से कि स्काला में 'टाइप' कीवर्ड क्या करता है


144

मैं स्काला के लिए नया हूं और मुझे वास्तव में typeकीवर्ड के बारे में बहुत कुछ नहीं मिला । मैं समझने की कोशिश कर रहा हूं कि निम्नलिखित अभिव्यक्ति का क्या मतलब हो सकता है:

type FunctorType = (LocalDate, HolidayCalendar, Int, Boolean) => LocalDate

FunctorType किसी तरह का उपनाम है, लेकिन यह क्या दर्शाता है?

जवाबों:


148

हाँ, प्रकार उर्फ ​​के FunctorType लिए सिर्फ एक आशुलिपि है

(LocalDate, HolidayCalendar, Int, Boolean) => LocalDate

टाइप उपनाम का उपयोग अक्सर बाकी कोड को सरल रखने के लिए किया जाता है: अब आप लिख सकते हैं

def doSomeThing(f: FunctorType)

जिसकी व्याख्या संकलक द्वारा की जाएगी

def doSomeThing(f: (LocalDate, HolidayCalendar, Int, Boolean) => LocalDate)

यह उदाहरण के लिए, कई कस्टम प्रकारों को परिभाषित करने से बचने में मदद करता है जो कि सिर्फ टुपल्स या अन्य प्रकारों पर परिभाषित कार्य हैं।

स्केला में प्रोग्रामिंग के इस अध्यायtype में उदाहरण के लिए वर्णित के रूप में कई अन्य दिलचस्प उपयोग के मामले भी हैं ।


198

वास्तव typeमें Scala में कीवर्ड एक जटिल प्रकार को कम करके अलियासिंग नाम से बहुत कुछ कर सकता है। यह टाइप सदस्यों का परिचय देता है ।

जैसा कि आप जानते हैं, एक वर्ग में क्षेत्र सदस्य और विधि सदस्य हो सकते हैं। खैर, स्काला भी एक वर्ग को टाइप सदस्य रखने की अनुमति देता है।

आपके विशेष मामले typeमें, वास्तव में, एक उपनाम पेश करना जो आपको अधिक संक्षिप्त कोड लिखने की अनुमति देता है। टाइप-सिस्टम के प्रदर्शन के समय टाइप सिस्टम केवल वास्तविक प्रकार के साथ उपनाम को बदलता है।

लेकिन आपके पास भी कुछ ऐसा हो सकता है

trait Base {
  type T

  def method: T
}

class Implementation extends Base {
  type T = Int

  def method: T = 42
}

किसी वर्ग के किसी अन्य सदस्य की तरह, टाइप सदस्य भी सार हो सकते हैं (आप केवल यह निर्दिष्ट नहीं करते कि उनका मूल्य वास्तव में क्या है) और कार्यान्वयन में ओवरराइड किया जा सकता है।

टाइप सदस्यों को जेनेरिक के दोहरे के रूप में देखा जा सकता है क्योंकि जेनेरिक के साथ आप जिन चीजों को लागू कर सकते हैं उनमें से अधिकांश को अमूर्त प्रकार के सदस्यों में अनुवाद किया जा सकता है।

तो हां, उन्हें अलियासिंग के लिए इस्तेमाल किया जा सकता है, लेकिन उन्हें सिर्फ इस तक सीमित न रखें, क्योंकि वे स्काला के प्रकार की एक शक्तिशाली प्रणाली हैं।

कृपया अधिक विवरण के लिए यह उत्कृष्ट उत्तर देखें:

स्केल: सार प्रकार बनाम जेनरिक


44
यह याद रखना महत्वपूर्ण है कि कक्षा के अंदर प्रकार का उपयोग करने से उपनाम के बजाय एक प्रकार का सदस्य बनता है। इसलिए यदि आपको केवल एक प्रकार का उपनाम चाहिए, तो इसे साथी ऑब्जेक्ट में परिभाषित करें।
रुडिगर क्लेहान

9

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

सार प्रकार:

type T

टी ऊपर कहते हैं कि इस प्रकार का उपयोग होने वाला है, अभी तक अज्ञात है, और कंक्रीट उपवर्ग के आधार पर, इसे परिभाषित किया जाएगा। प्रोग्रामिंग अवधारणाओं को समझने के लिए हमेशा सबसे अच्छा तरीका एक उदाहरण प्रदान कर रहा है: मान लीजिए कि आपके पास निम्नलिखित परिदृश्य हैं:

टाइप एब्सट्रैक्शन के बिना

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

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

सार प्रकार के साथ

अब निम्नलिखित कोड देखें:

  val cow1: Cow = new Cow
  val cow2: Cow = new Cow

  cow1 eat new cow1.SuitableFood
  cow2 eat new cow1.SuitableFood

  val tiger: Tiger = new Tiger
  cow1 eat new tiger.SuitableFood // Compiler error

कंपाइलर खुश है और हम अपने डिजाइन में सुधार करते हैं। हम अपनी गाय को गाय के साथ भोजन कर सकते हैं। अच्छा भोजन और संकलक हमें भोजन के साथ गाय को खिलाने से रोकता है जो टाइगर के लिए उपयुक्त है। लेकिन क्या होगा अगर हम गाय 1 उपयुक्तफूड और गाय 2 सूटेबेफूड के प्रकार के बीच अंतर करना चाहते हैं। दूसरे शब्दों में, कुछ परिदृश्यों में यह बहुत उपयोगी होगा यदि हम जिस मार्ग तक पहुँचते हैं (निश्चित रूप से वस्तु के माध्यम से) मूल रूप से बात करते हैं। स्काला में उन्नत सुविधाओं के लिए धन्यवाद, यह संभव है:

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

  class Cow extends Animal {
    class Grass extends Food
    type SuitableFood = Grass
    override def eat(food: this.SuitableFood): Unit = {}
  }

  class Tiger extends Animal {
    class Meat extends Food
    type SuitableFood = Meat
    override def eat(food: this.SuitableFood): Unit = {}
  }

अब यदि आप इस कोड को संकलित करने का प्रयास करते हैं:

  1. val cow1: Cow = new Cow
  2. val cow2: Cow = new Cow

  3. cow1 eat new cow1.SuitableFood
  4. cow2 eat new cow1.SuitableFood // compilation error

लाइन 4 पर आपको एक त्रुटि दिखाई देगी क्योंकि ग्रास अब गाय का एक आंतरिक वर्ग है, इसलिए ग्रास का एक उदाहरण बनाने के लिए, हमें एक गाय ऑब्जेक्ट की आवश्यकता है और यह गाय ऑब्जेक्ट पथ निर्धारित करता है। तो 2 गाय वस्तुएं 2 अलग-अलग मार्ग को जन्म देती हैं। इस परिदृश्य में, काउ 2 केवल विशेष रूप से इसके लिए बनाए गए भोजन को खाना चाहता है। इसलिए:

cow2 eat new cow2.SuitableFood

अब हर कोई खुश है :-)


5

केवल एक उदाहरण देखें कि "प्रकार" को उपनाम के रूप में कैसे उपयोग किया जाए:

type Action = () => Unit

उपरोक्त परिभाषा एक्शन के प्रकार (मेथोड्स) का एक उपनाम होने के लिए क्रिया को परिभाषित करती है जो एक खाली पैरामीटर सूची और उस वापसी इकाई को लेती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.