2015-08-22 15 views
5

मैं स्काला में पुस्तक प्रोग्रामिंग की धारा 20.7 पढ़ रहा था और यही कारण है, जबकि इस कोड को संकलित करता है मैं सोच रहा था:स्काला प्रकार: क्लास ए टी जहां टी है के बराबर नहीं है: प्रकार टी = एक

class Food 
class Fish extends Food 
class Grass extends Food 

abstract class Animal { 
    type SuitableFood <: Food 
    def eat(food: SuitableFood) 
} 


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


val bessy: Animal = new Cow 

bessy eat (new bessy.SuitableFood) 

इस कोड ऐसा नहीं करता (कोड के बाकी, पहले की तरह ही केवल अंतिम पंक्ति परिवर्तन है):

bessy eat (new Grass) 

और जहाँ तक मैं समझता हूँ कि घास के प्रकार Cow.SuitableFood की ही है। -> घास के बजाय एक प्रकार का खाद्य

bessy प्रकार पशु का है, तो कैसे संकलक पता कर सकते हैं कि यह एक प्रकार SuitableFood की जरूरत है:

इसके अलावा, मैं इस उदाहरण के बारे में एक और सवाल है? 'एक नया खाद्य प्रदान करने के लिए कोशिश कर रहा है कारण मुझे प्रकार मेल नहीं खाता का एक संकलन त्रुटि देता है, लेकिन वर्ग पशु एक प्रकार खाद्य की जरूरत है और bessy के प्रकार स्पष्ट रूप से परिभाषित किया गया है: पशु

+0

सुझाव: इस प्रश्न में टैग _path-dependent-type_ जोड़ें। यह किसी ऐसे व्यक्ति से उत्तर आकर्षित कर सकता है जो वास्तव में इस तरह की कठिनाई के बारे में और जानता है। (मैं अभी भी पथ-निर्भर प्रकारों के साथ संघर्ष कर रहा हूं।) –

+0

@BenKovitz जोड़ा गया, धन्यवाद। – vicaba

उत्तर

10

क्योंकि bessieCow से Animal घोषित किया जाता है बल्कि यह है। bessie.SuitableFood एक "पथ-निर्भर प्रकार" है (नीचे देखें)।

इस प्रयास करें:

val clarabelle: Cow = new Cow 

clarabelle eat (new Grass) 

यह काम करता है क्योंकि संकलक मान सकते हैं कि clarabelle.SuitableFood = Grassclarabelle से की घोषित प्रकार।

bessie के बाद से Animal घोषित किया जाता है, नहीं Cow, संकलक सुरक्षित रूप से नहीं मान सकते हैं कि bessie.SuitableFood = Grass। * जब आप कहते हैं कि new bessie.SuitableFood, संकलक कोड वास्तविक bessie वस्तु को देखने और उचित प्रकार का एक नया उदाहरण उत्पन्न करने के लिए उत्पन्न करता है। bessie.SuitableFood एक "पथ-निर्भर प्रकार" है: "path" (bessie. भाग) जो अंतिम पहचानकर्ता (SuitableFood) की ओर जाता है वास्तव में इस प्रकार का हिस्सा है। यह आपको एक ही कक्षा के प्रत्येक व्यक्तिगत ऑब्जेक्ट के लिए एक प्रकार का कस्टम संस्करण प्राप्त करने में सक्षम बनाता है।


* ठीक है, वास्तव में, मुझे लगता है कि अगर संकलक एक छोटे से होशियार थे, यह उस bessie.SuitableFood = Grass अनुमान कर सकता है, के बाद से bessie एक val, नहीं एक var है, और इसलिए अपने प्रकार नहीं बदलेगा। दूसरे शब्दों में, संकलक को यह जानना चाहिए कि bessie को Animal घोषित किया गया है, वह वास्तव में Cow है। शायद कंपाइलर का भविष्य का संस्करण इस ज्ञान का उपयोग करेगा, और शायद एक अच्छा कारण है कि यह एक अच्छा विचार नहीं होगा, जो कि मैं उससे ज्यादा विशेषज्ञ हूं, जो हमें बताएगा। (पोस्टस्क्रिप्ट: एक ने अभी किया! ट्रैविस ब्राउन की टिप्पणी नीचे देखें।)

+7

अपने फुटनोट के बारे में: यदि आप किसी चीज़ पर एक प्रकार का एनोटेशन डालते हैं, तो संकलक इसे उस प्रकार के रूप में पेश करने जा रहा है, भले ही यह _could_ कुछ और विशिष्ट बताए। यदि आप टाइप सदस्य का ट्रैक रखना चाहते हैं लेकिन सबटाइप नहीं चाहते हैं तो आपको 'वैल बेस्सी: एनिमल {टाइप SuitableFood = Grass}' जैसे प्रकार के परिशोधन का उपयोग करना होगा। –

1

आपके प्रश्न के दूसरे भाग के बारे में: यह नहीं है। Animal यह निर्दिष्ट नहीं करता है कि इसका भोजन Food है, लेकिन Food के कुछ उप प्रकार। क्या संकलक इसे स्वीकार करेगा, आपके उदाहरण की तरह कोड संकलित होगा, और गलत तरीके से। कंपाइलर यह नहीं जानता कि आवश्यक उप प्रकार Grass है (यही कारण है कि eat(new Grass) या तो काम नहीं करता है), यह सिर्फ इतना जानता है कि कुछ गाय हैं जो आपकी गाय नहीं खा सकती हैं और इसके बारे में सतर्क हैं।

1

मुझे विश्वास है कि bessy eat (new bessy.SuitableFood) संकलन एक बग है (जिसे 2.11 में तय किया गया था)।क्योंकि Animal का एक और सबटाइप SuitableFood हो सकता है जिसके लिए new कोई समझ नहीं आता है, उदा। type SuitableFood = Food या यहां तक ​​कि type SuitableFood = Food with Int (Food with IntFood का एक बिल्कुल अच्छा उप प्रकार है!)।

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