2017-05-31 15 views
5

(स्काला 2.11.8)स्काला निहित संकल्प typeclasses

निम्नलिखित कोड पर विचार करें:

  1. क्यों नहीं करता है ': मैं कोड के इस टुकड़े के बारे में सवाल का एक समूह है

    object ScalaTest extends App { 
        class Wrapper { 
        import Wrapper._ 
    
        def init(): Unit = { 
         // "could not find implicit value for parameter tc: ScalaTest.Wrapper.TC[Int]" 
         printWithTC(123) 
    
         // Compiles 
         printWithTC(123)(IntTC) 
    
         // Compiles again! 
         printWithTC(132) 
        } 
        } 
    
        object Wrapper { 
        trait TC[A] { 
         def text(a: A): String 
        } 
    
        implicit object IntTC extends TC[Int] { 
         override def text(a: Int) = s"int($a)" 
        } 
    
        def printWithTC[A](a: A)(implicit tc: TC[A]): Unit = { 
         println(tc.text(a)) 
        } 
        } 
    
        (new Wrapper).init() 
    } 
    

    टी IntTC पहली जगह में हल हो गया है?

  2. यह एक बार उपयोग किए जाने के बाद क्यों संकलित करता है? (यदि आप पहले आमंत्रण पर टिप्पणी करते हैं, कोड काम करता है)
  3. टाइपक्लास इम्प्लिकेट्स को ठीक से हल करने के लिए कहां रखा जाना चाहिए?
+3

मुझे नहीं पता कि क्या हो रहा है, लेकिन सिर्फ ध्यान दिया गया है कि यदि आप ऑब्जेक्ट को कक्षा से पहले ले जाते हैं, तो कोड भी संकलित करता है। – Dima

उत्तर

3

एक स्पष्ट वापसी प्रकार के साथ val का उपयोग करें। https://github.com/scala/bug/issues/801 और https://github.com/scala/bug/issues/8697 (दूसरों के बीच) देखें।
लागू वस्तुओं में निहित vals के रूप में एक ही समस्या है और अनुमानित रिटर्न प्रकारों के साथ defs। आपके दूसरे प्रश्न के लिए: जब IntTC स्पष्ट रूप से उपयोग किया जाता है तो आप कंपाइलर को टाइपशेक करने के लिए मजबूर करते हैं, इसलिए उस बिंदु के बाद इसका प्रकार ज्ञात है और निहित खोज द्वारा पाया जा सकता है।

class Wrapper { 
    import Wrapper._ 

    def init(): Unit = { 
    // Compiles 
    printWithTC(123) 

    // Compiles 
    printWithTC(123)(IntTC) 

    // Compiles 
    printWithTC(132) 
    } 
} 

object Wrapper { 
    trait TC[A] { 
    def text(a: A): String 
    } 

    implicit val IntTC: TC[Int] = new TC[Int] { 
    override def text(a: Int) = s"int($a)" 
    } 

    def printWithTC[A](a: A)(implicit tc: TC[A]): Unit = { 
    println(tc.text(a)) 
    } 
} 

तुम सच में अपने निहित चाहते हैं एक वस्तु की तरह lazily मूल्यांकन किया जाना, आप एक स्पष्ट प्रकार के साथ एक implicit lazy val उपयोग कर सकते हैं।

0

इसके उपयोग से पहले निहित परिभाषित करें।

object Wrapper { 
    trait TC[A] { 
    def text(a: A): String 
    } 

    implicit object IntTC extends TC[Int] { 
    override def text(a: Int) = s"int($a)" 
    } 

    def printWithTC[A](a: A)(implicit tc: TC[A]): Unit = { 
    println(tc.text(a)) 
    } 
} 

class Wrapper { 
    import Wrapper._ 

    def init(): Unit = { 
    // "could not find implicit value for parameter tc: ScalaTest.Wrapper.TC[Int]" 

    printWithTC(123) 

    // Compiles 
    printWithTC(123)(IntTC) 

    // Compiles again! 
    printWithTC(132) 
    } 
} 

(new Wrapper).init() 
+0

क्या हम कक्षा के अंदर पहली पंक्ति के रूप में कक्षा के दायरे में पूरी ऑब्जेक्ट सामग्री आयात नहीं कर रहे हैं? साथ ही, कक्षा के बाद साथी ऑब्जेक्ट को परिभाषित करना आम है (उदा। Http://docs.scala-lang.org/tutorials/tour/singleton-objects.html) तो यह काफी हैकी कामकाज है –