सवालस्कैला में एक प्रकार के प्रक्षेपण पर विशेषज्ञ कैसे करें?
का विवरण एक प्रकार T
कि एक सार प्रकार सदस्य A
शामिल पर विचार करें:
trait T {
type A
}
मैं एक वर्ग है कि एक प्रकार पैरामीटर के रूप में एक T0 <: T
लेता है बनाना चाहते हैं, लेकिन माहिर पर प्रक्षेपणT0#A
पर टाइप करें। उदाहरण के लिए, निम्न में, विधि foo
विशिष्ट हो सकती है? @specialized
साथ T0
व्याख्या वांछित परिणाम प्राप्त नहीं होगा
class Foo[T0 <: T] {
def foo(a: T0#A, f: T0#A => T0#A) = f(a)
}
ध्यान दें कि। foo
टाइप प्रोजेक्शन T#A
पर विशेषज्ञता का कोई अच्छा तरीका है?
एक सीमित समाधान: अतिरिक्त पैरामीटर
साथ विशेष माता पिता वर्ग से विरासत इस विशेष मामले में, यहाँ एक तरह से T0#A
विशेषज्ञता हासिल करने में है:
trait SpecializedFoo[@specialized A0, T0 <: T] {
def foo(a: A0, f: A0 => A0) = f(a)
}
class Foo2[T0 <: T] extends SpecializedFoo[T0#A, T0]
विशेष माता पिता वर्ग SpecializedFoo
से इनहेरिट तक , हम सुनिश्चित करते हैं कि Foo2.foo
विशिष्ट है।
विशेषज्ञता के सत्यापन
, कि Foo2.foo
, लेकिन नहीं Foo.foo
सत्यापित करने के लिए
trait ExplicitT extends T {
type A = Double
}
object Test {
def test1 = (new Foo[ExplicitT]).foo(1.0, _ + 1.0)
def test2 = (new Foo2[ExplicitT]).foo(1.0, _ + 1.0)
}
बाईटकोड कर सकते हैं हम उन्हें एक स्पष्ट T
जहां T#A
एक आदिम डबल है के साथ कॉल कर सकते हैं, विशेष है, कमांड के साथ आरईपीएल से जांच की जा सकती है ": javap -v test",
public double test1();
Code:
Stack=4, Locals=1, Args_size=1
0: new #16; //class Foo
3: dup
4: invokespecial #18; //Method Foo."<init>":()V
7: dconst_1
8: invokestatic #24; //Method scala/runtime/BoxesRunTime.boxToDouble:(D)Ljava/lang/Double;
11: new #26; //class Test$$anonfun$test1$1
14: dup
15: invokespecial #27; //Method Test$$anonfun$test1$1."<init>":()V
18: invokevirtual #31; //Method Foo.foo:(Ljava/lang/Object;Lscala/Function1;)Ljava/lang/Object;
21: invokestatic #35; //Method scala/runtime/BoxesRunTime.unboxToDouble:(Ljava/lang/Object;)D
24: dreturn
LineNumberTable:
line 13: 0
public double test2();
Code:
Stack=5, Locals=1, Args_size=1
0: new #38; //class Foo2
3: dup
4: invokespecial #39; //Method Foo2."<init>":()V
7: dconst_1
8: new #41; //class Test$$anonfun$test2$1
11: dup
12: invokespecial #42; //Method Test$$anonfun$test2$1."<init>":()V
15: invokeinterface #48, 4; //InterfaceMethod SpecializedFoo.foo$mcD$sp:(DLscala/Function1;)D
20: dreturn
LineNumberTable:
line 14: 0
ध्यान दें कि मुक्केबाजी test1
में दिखाई देती है लेकिन test2
नहीं है।
सीमाएं
संपादित 7/9 चाल ऊपर और अधिक सीमित की तुलना में मैं पहली बार में महसूस किया है। यह बिल्कुल भी इस मामले विशेषज्ञता के लिए काम नहीं करेगा:
trait T {
type A
def x: A
def f: A => Double
}
class Foo[T0 <: T] {
def foo(t: T0) = t.f(t.x)
}
मुझे कोई कारण नहीं क्यों एक (काल्पनिक) संकलक A
सिद्धांत में पर विशेषज्ञ नहीं कर सकता है; एक सामान्य, विशेष संस्करण केवल प्रयोग योग्य होंगे जब एक विशिष्ट T#A
संकलन समय पर जाना जाता है। प्राकृतिक व्यावहारिक समाधान A
को T
के प्रकार पैरामीटर में उठाना है, लेकिन मैं सोच रहा था कि क्या मैं इससे बच सकता हूं।
विचार यह है कि मैं एक कार्यान्वयन 'कक्षा बार पर विशेष विधियों को चाहता हूं जो फू [एस]' बढ़ाता है, जहां 'एस <: टी' संकलित समय पर स्पष्ट रूप से जाना जाता है और 'एस # ए' एक आदिम है। मुझे पता है कि यह काम कर सकता है क्योंकि ऊपर की चाल का उपयोग (यानी, एक अतिरिक्त प्रकार पैरामीटर वाला 'स्पेशलफू' पैरेंट क्लास) मैं मुक्केबाजी को खत्म करने में सक्षम था, जिसे मैंने स्कैला आरपीएल में ": जावा-वी" के साथ सत्यापित किया था। प्रश्न में नमूना कोड निश्चित रूप से एक सरलीकरण है ... शायद मुझे और विवरण देना चाहिए। –
मैंने इस प्रश्न को अद्यतन किया कि मुक्केबाजी कैसे दिखाई देती है, और विशेषज्ञता के साथ इसे कैसे हटाया जा सकता है। –