2016-10-28 2 views
0

Чтобы понять, как «неявный» работает в Scala, я написал следующий код, но он не дает ожидаемого результата. Может кто-нибудь, пожалуйста, дайте мне знать, что я делаю неправильно здесь«неявный» в scala не работает как мысль

Я (думал) Я понимаю использование «неявного» (что явно не так). У меня есть три класса: Plant, Dog и myPet. У собаки есть функция «звук», которая возвращает «woof». У завода есть функция «tallOrShort», которая возвращает «высокий». Эти функции описывают особенности собак и растений.

Я хочу написать общий код в myPet, на который я могу передать экземпляр Dog или Plant. Я называю эту функцию «описать». Функция описания должна печатать «woof» для экземпляров Dog и «высокий» для экземпляров Plant.

Собака и завод являются самостоятельными классами (без подтипа). Я думал, что могу использовать «неявный», чтобы «добавить» эту функциональность в классе Dog и Plant. Мое понимание заключается в том, что, используя неявное, Dog или Plant могут быть неявно преобразованы в «что-то», которое затем может вызвать «звук» или «tallOrShort» для собак и растений соответственно. Я написал следующий код, но он не работает.

Я начал с класса Dog, чтобы начать с

//create Dog 
scala> class Dog { 
| def sound = "woof" 
| } 

defined class Dog 

//create trait (the contract interface which Dog can be member of 
scala> trait myPetTrait[A] { 
| def describePet(a:A):String 
| } 

defined trait myPetTrait 

//implicit conversion should happen using this code? 
scala> implicit object dogIsPet extends myPetTrait[Dog] { 
| def describePet(d:Dog) = d.sound 
| } 

defined object dogIsPet 

Теперь первый, я думал об определении только обобщенную функцию «описать», как следует, но я не в состоянии передать собаку или завод экземпляра к нему.

//'describe' function. It should work for both Dog and Plant 
scala> def describe[A](implicit pt:myPetTrait[A]) = {println(pt.describePet(_:A))} 
describe: [A](implicit pt: myPetTrait[A])Unit 

scala> describe(new Dog) 
<console>:21: error: type mismatch; 
found : Dog 
required: myPetTrait[?] 
describe(new Dog) 

Вопрос 1 - Что случилось с выше? Не следует ли перевести собаку на myPetTrait [Dog]?

Затем я решил создать класс (myPet) и определить «описать» в этом классе. Это не работает либо

//metPet It should work for both Dog and Plant  
scala> class myPet[A](a:A) { 
| def describe[A](implicit pt:myPetTrait[A]) = {println(pt.describePet(_:A))} 
| } 
defined class myPet 

scala> new myPet(new Dog).describe 
<function1> 

Вопрос 2 - Почему это компиляция по крайней мере, если я надену описать в myPet? Почему я получаю функцию буквальные (FUNCTION1), а не печать я ожидаю

Чтобы экспериментировать, я снова начал REPL и объявил завод, а также перед созданием описания и myPet

//new REPL session. created Dog 
scala> class Dog { 
| def sound = "woof" 
| } 
defined class Dog 

//created plant 
scala> class Plant { 
| def tallOrShort = "tall" 
| } 

defined class Plant 
//created trait 
scala> trait myPetTrait[A] { 
| def describePet(a:A):String 
| } 

defined trait myPetTrait 

//code which should I think help in implicit conversion 
scala> implicit object plantIsPet extends myPetTrait[Plant] { 
| def describePet(p:Plant) = p.tallOrShort 
| } 
defined object plantIsPet 

//describe still doesn't work 
//describe shuold work for both Plant and Animal 
scala> def describe[A](implicit pt:myPetTrait[A]) = {println(pt.describePet(_:A))} 
describe: [A](implicit pt: myPetTrait[A])Unit 

//not sure why this error comes 
scala> describe(new Dog) 
<console>:21: error: type mismatch; 
found : Dog 
required: myPetTrait[?] 
describe(new Dog) 

//get ambiguity error in this line 
scala> new myPet(new Dog).describe  //myPet gives ambiguity error 

я неоднозначный неявным значения EROR о том, что оба объекта dogIsPet типа dogIsPet.type и объект plantIsPet матча plantIsPet.type типа Ожидаемый тип myPetTrait [A]

Вопрос 3 - почему жалуются на Scala двусмысленности? Вероятно, потому, что типы dogIsPet.type и plantisPet.type имеют один и тот же тип. Как заставить этот код работать?

благодаря

ответ

0

Я думаю, вы пропустили это (describe должны a типа A и implicit контракт)

определяют describe как это в myPet

class myPet[A](a:A) { 
def describe(implicit pt:myPetTrait[A]) = { 
    println(pt.describePet(a)) 
} 
} 

describe вне myPet может быть объявлено следующим образом

def describe[A](a: A)(implicit pt:myPetTrait[A]) = {println(pt.describePet(a))} 

Scala имеет специальный синтаксис для этого

def describe[A: myPetTrait](a: A) = println(implicitly[myPetTrait[A]].describePet(a)) 

Scala РЕПЛО

scala> def describe[A](a: A)(implicit pt:myPetTrait[A]) = {println(pt.describePet(a))} 
describe: [A](a: A)(implicit pt: myPetTrait[A])Unit 

scala> describe[Plant](new Plant) 
tall 

или использовать лестницу синтаксического

scala> def describe[A: myPetTrait](a: A) = println(implicitly[myPetTrait[A]].describePet(a)) 
describe: [A](a: A)(implicit evidence$1: myPetTrait[A])Unit 

scala> describe[Plant](new Plant) 
tall 

scala> trait myPetTrait[A] { def describePet(a:A):String } 
defined trait myPetTrait 

scala> class Dog { def sound = "woof" } 
defined class Dog 

scala> implicit object dogIsPet extends myPetTrait[Dog] { def describePet(d:Dog) = d.sound } 
defined object dogIsPet 

scala> def describe[A: myPetTrait](a: A) = println(implicitly[myPetTrait[A]].describePet(a)) 
defined function describe 

scala> implicit object dogIsPet extends myPetTrait[Dog] { def describePet(d:Dog) = d.sound } 
defined object dogIsPet 

scala> describe[Dog](new Dog) 
woof 

scala> class myPet[A](a:A) { 
     def describe(implicit pt:myPetTrait[A]) = { 
     println(pt.describePet(a)) 
     } 
    } 
defined class myPet 

scala> new myPet[Dog](new Dog).describe 
woof 

Полного код в одном месте

Main.scala

object Implicits { 
    trait myPetTrait[A] { 
    def describePet(a:A):String 
    } 

    class Dog { 
    def sound = "woof" 
    } 

    class Plant { 
    def tallOrShort = "tall" 
    } 

    //evidence for Plant 
    implicit object plantIsPet extends myPetTrait[Plant] { 
    def describePet(p:Plant) = p.tallOrShort 
    } 

    //evidence for Dog 
    implicit object dogIsPet extends myPetTrait[Dog] { 
    def describePet(d:Dog) = d.sound 
    } 

    def describe[A](a: A)(implicit pt:myPetTrait[A]) = { 
    println(pt.describePet(a)) 
    } 

    //syntactic sugar 
    def describe2[A : myPetTrait](a: A) = 
    println(implicitly[myPetTrait[A]].describePet(a)) 

    class myPet[A](a:A) { 
    def describe(implicit pt:myPetTrait[A]) = { 
     println(pt.describePet(a)) 
    } 
    } 

} 


object Main { 

    import Implicits._ 

    def main(args: Array[String]): Unit = { 
    describe(new Dog) 
    describe(new Plant) 
    describe2(new Dog) 
    describe2(new Plant) 

    new myPet[Dog](new Dog).describe 
    new myPet[Plant](new Plant).describe 
    } 
} 

выход:

woof 
tall 
woof 
tall 
woof 
tall 
+0

@ManuChadha .. я приклеила точный код ... в ответ – pamu

+0

@ManuChadha скажите мне, где проблема – pamu

+0

@ManuChadha снова проверьте вывод Scala REPL в ответе – pamu

Смежные вопросы