2009-04-22 16 views
13

मैं इस विधि का उपयोग करने में सक्षम होना चाहता हूं, एक विधि को परिभाषित करने के लिए जो एक अपरिवर्तनीय केस क्लास के नए उदाहरण बनाता है। कुछ इस तरह:इस उदाहरण का उपयोग नए उदाहरणों के लिए क्यों नहीं किया जा सकता

trait Expression 
{ 
    def left : Expression 
    def right : Expression 

    def new_with_changes(l : Expression, r : Expression) : this.type 
} 

case class Derived(left : Expression, right : Expression) 
{ 
    def new_with_changes(l : Expression, r : Expression) : this.type = 
    { 
    new Derived(left, right) 
    } 
} 

दुर्भाग्य से, संकलक

test.scala:13: error: type mismatch; 
found : Derived 
required: Derived.this.type 
    new Derived(left, right) 
    ^
one error found 

शिकायत नया मामला वर्ग this.type कैसे मेल नहीं खाती हो?

यदि मैं इसे बदलता हूं। Base.new_with_changes में आधार पर टाइप करें और Derived.new_with_changes में व्युत्पन्न है, लेकिन ऐसा लगता है कि यह इस प्रकार की विशेषता पर अनुपलब्ध है।

संपादित करें: सवाल का असली इरादा यह है कि डाउनकास्ट के कॉलर को डाउनकास्ट करने का एक समान तरीका नहीं है, जैसा कि यह टाइप करता है, लेकिन सामान्य प्रकार के लिए। मुझे नहीं लगता कि यह आसान होगा, लेकिन यह अच्छा होगा।

उत्तर

7

[नोट: मैं की सिफारिश नहीं कर रहा हूँ आप यह करते हैं कि।] वहाँ एक निष्पक्ष है मौका आप जो चाहते हैं उसे पूरा कर सकते हैं। इस पर कास्ट एक प्रकार का झूठ है, लेकिन JVM को यह नहीं पता है और अपवाद नहीं फेंक सकता क्योंकि सिंगलटन प्रकार एक स्केल अवधारणा है।

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

trait Expression 
{ 
    def left : Expression 
    def right : Expression 

    def new_with_changes(l : Expression, r : Expression) : this.type 
} 

case class Derived1(left : Expression, right : Expression) extends Expression { 
    def new_with_changes(l : Expression, r : Expression) = 
    Derived1(left, right).asInstanceOf[this.type] 

    def foo() = "Derived1" 
} 

case class Derived2(left : Expression, right : Expression) extends Expression { 
    def new_with_changes(l : Expression, r : Expression) = 
    Derived2(left, right).asInstanceOf[this.type] 

    def bar() = "Derived2" 
} 

और कार्रवाई में:

scala> Derived1(Derived1(null,null), null) 
res0: Derived1 = Derived1(Derived1(null,null),null) 

scala> res0.new_with_changes(res0, null).bar 
<console>:6: error: value bar is not a member of Derived1 
     res0.new_with_changes(res0, null).bar 
             ^

scala> res0.new_with_changes(res0, null).foo 
res2: java.lang.String = Derived1 

scala> Derived2(Derived2(null, null), null) 
res3: Derived2 = Derived2(Derived2(null,null),null) 

scala> res3.new_with_changes(null, res3).foo 
<console>:6: error: value foo is not a member of Derived2 
     res3.new_with_changes(null, res3).foo 
             ^

scala> res3.new_with_changes(null, res3).bar 
res6: java.lang.String = Derived2 
+0

हैकी, लेकिन यह काम करता है। अगर हम इस तरह कुछ भाषा में प्राप्त कर सकते हैं, तो यह अच्छा होगा। –

8

यह। टाइप इस विशेष उदाहरण का अद्वितीय प्रकार है। यह एक सिंगलटन प्रकार है - एक ही वर्ग के किसी भी अन्य उदाहरण से एक अलग प्रकार। यह

class Foo { def f : this.type = this} 

काम करता है लेकिन इस

class Foo { def f : this.type = new Foo} 

this.type है कि अक्सर की जरूरत नहीं है नहीं है, लेकिन यह कुछ कमी है कि अन्यथा व्यक्त नहीं किया जा सकता

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

scala> class Outer{ class Inner { def outer : Outer.this.type = Outer.this}; def f(x : Inner) = println("ok")} 
defined class Outer 

scala> val o1 = new Outer 
o1: Outer = [email protected] 

scala> val o2 = new Outer 
o2: Outer = [email protected] 


scala> val in1 = new o1.Inner 
in1: o1.Inner = [email protected] 

scala> val in2 = new o2.Inner 
in2: o2.Inner = [email protected] 

scala> val o3 = in1.outer 
o3: o1.type = [email protected] 

scala> o1.f(new o3.Inner) 
ok 

scala> o1.f(new o2.Inner) 
<console>:8: error: type mismatch; 
found : o2.Inner 
required: o1.Inner 
     o1.f(new o2.Inner) 

यह लेख उपवर्ग सीमाओं के पार चेनिंग विधि सक्षम करने के लिए this.type का उपयोग करने का एक और अच्छा उदाहरण है: http://scalada.blogspot.com/2008/02/thistype-for-chaining-method-calls.html

scala> class A { def method1: this.type = this } 
defined class A 

scala> class B extends A { def method2: this.type = this } 
defined class B 

scala> val b = new B 
b: B = [email protected] 

scala> b.method1.method2 
res3: b.type = [email protected] 
+2

यह करने के लिए एक अच्छा तरीका होगा कि मैं क्या करना चाहूंगा, इसके अलावा। टाइप, जहां बेस क्लास विधि को उप प्रकार के उदाहरण को वापस करने के लिए घोषित किया जा सकता है, जिसे कॉलर डाउनकास्ट करेगा, वैसे ही इस के साथ कॉलर कोड। टाइप करता है। –

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

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