2015-04-28 11 views
10

मैं स्केला में निम्न पदानुक्रम के साथ समस्या है:स्केला जेनरिक और विरासत

class ScalaGenericTest { 
    def getValue[A, B <: Abstract[A]](clazz: B): A = clazz.a 

    def call: String = { 
    val sub: Subclass = new Subclass 
    getValue(sub) 
    } 
} 

class Subclass extends Abstract[String] { 
    def a: String = "STRING" 
} 

abstract class Abstract[A] { 
    def a: A 
} 

संकलक getValue कार्य करने के लिए कॉल में जेनेरिक पैरामीटर एक बाध्य करने के लिए सक्षम होने के लिए प्रतीत नहीं होता है - मैं लगता है कि यह सबक्लास की परिभाषा से इसका अनुमान लगाने में सक्षम होना चाहिए।

अनुमानित प्रकार तर्क [कुछ भी नहीं है, उपवर्ग] विधि getValue के प्रकार पैरामीटर सीमा के अनुरूप नहीं है [ए, बी <: सार [एक]]

यह अगर काम करता है संकलन त्रुटि इस प्रकार है मैं स्पष्ट रूप से विधि के लिए जेनेरिक प्रकार तर्कों को पास करता हूं, यानी getValue[String,Subclass](sub) लेकिन निश्चित रूप से संकलक इसे अनुमान लगाने में सक्षम होना चाहिए?

ही पदानुक्रम जावा में ठीक काम करता है:

public class JavaGenericTest { 

    public <T,U extends Abstract<T>> T getValue(U subclass) { 
     return subclass.getT(); 
    } 

    public String call(){ 
     Subclass sub = new Subclass(); 
     return getValue(sub); 
    } 

    private static class Subclass extends Abstract<String> { 
     String getT(){ 
      return "STRING"; 
     } 
    } 

    private static abstract class Abstract<T> { 
     abstract T getT(); 
    } 
} 

मैं स्काला के सुंदर नया हूँ वहाँ शायद कुछ सूक्ष्मता है कि मैं याद कर रहा हूँ, इसलिए।

किसी भी मदद के लिए अग्रिम धन्यवाद!

उत्तर

9

यह स्कैला के प्रकार की अनुमान में एक सीमा है। इस मुद्दे को SI-2272 में वर्णित किया गया है (उदाहरण में प्रत्यारोपण का उपयोग किया जाता है, लेकिन स्पष्ट रूप से इसका उपयोग करते समय भी यही त्रुटि होती है)। इसे के रूप में बंद कर दिया गया है को ठीक नहीं करेगा।

उस समस्या में, एड्रियान मूरर्स उन दोनों बाधाओं से बचने की सलाह देता है जिनमें दोनों तरफ प्रकार चर होते हैं। अर्थात। B <: Abstract[A]। दूसरे प्रकार के पैरामीटर से पूरी तरह से बचने के लिए एक आसान काम-आसपास होगा।

def getValue[A](clazz: Abstract[A]): A = clazz.a 

scala> val sub = new Subclass 
sub: Subclass = [email protected] 

scala> getValue(sub) 
res11: String = STRING 

साथ ही, Adriaan भी एक अंतर्निहित <:< चारों ओर एक और काम के रूप में प्रयोग करने का एक तरीका प्रदान की है। अपने उदाहरण के संदर्भ में कहें, यह दिखाई देगा:

def getValue[A, B](b: B)(implicit ev: B <:< Abstract[A]): B = b.a 

कहाँ <:< का एक उदाहरण के माध्यम से Predef परोक्ष प्रदान की जाती है।

+0

तुम भी 'बी <% सार [एक]' साथ सामान्य पैरामीटर पर एक अंतर्निहित दृश्य का उपयोग कर सकते हैं। मुझे लगता है कि इसे बहिष्कृत किया जा सकता है, लेकिन यह अंतर्निहित तर्क तर्क प्रकार अनुमान के लिए पर्याप्त सबूत है। –

+0

ग्रेट उत्तर। मैंने निहित तर्क दृष्टिकोण पर विचार किया लेकिन मूल कारण नहीं था कि एक अच्छा कारण नहीं देख सका। <% का उपयोग करके सीमाएं देखें निश्चित रूप से बहिष्कृत की गई है। – paulyb

1

जस्टिन के अलावा और एम-जेड के जवाब के रूप में, एक और तरीका समान घोषणा दो प्रकार पैरामीटर रखने बनाने के लिए:

def getValue[A, B](clazz: B)(implicit evidence: B <:< Abstract[A]): A = clazz.a 
3

मैं एक समय में बहुत ही समस्या है। और दूर करने के लिए बड़े अंतर्निहित साक्ष्य हैक बनाया। बाद में मैंने गलती से स्केला संग्रह API दस्तावेज़ों में देखने के लिए और एक समाधान मिला: http://www.scala-lang.org/api/2.11.4/index.html#scala.collection.generic.GenericTraversableTemplate

class ScalaGenericTest { 
    def getValue[A, B[X] <: Abstract[X]](clazz: B[A]): A = clazz.a 

    def call: String = { 
    val sub: Subclass = new Subclass 
    getValue(sub) 
    } 
} 

class Subclass extends Abstract[String] { 
    def a: String = "STRING" 
} 

abstract class Abstract[A] { 
    def a: A 
} 
संबंधित मुद्दे