'隐'在scala中没有按照思路工作

时间:2016-10-28 08:16:57

标签: scala implicit-conversion

为了理解隐含的'在Scala中工作,我写了下面的代码,但它没有给我预期的结果。有人可以让我知道我在这里做错了什么

我(想)我明白使用'隐含' (显然不是这样)。我有三个班,Plant,Dog和myPet。狗有一个功能'声音'返回" woof"。植物有一个功能" tallOrShort"返回" tall"。这些功能描述了狗和植物的特征。

我想在myPet中编写一个通用代码,我可以传递一个Dog或Plant实例。我把这个功能叫做“描述”。描述功能应该打印" woof"对于Dog实例和" tall"对于植物实例。

狗和植物是独立的类(没有亚型)。我以为我可以使用隐含的'到"添加" Dog and 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'如下,但我无法将狗或植物实例传递给它。

//'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 [狗]吗?

然后我想创建一个类(myPet)并定义&#39;描述&#39;在那堂课。这不起作用

//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中使用describe进行编译?为什么我得到一个函数文字(function1),而不是我期望的打印

为了继续进行实验,我再次启动了REPL并在创建describe和myPet

之前声明了Plant
//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

我得到含糊不清的隐含值,指出dogIsPet.type类型的对象dogIsPet和plantIsPet.type类型的对象plantIsPet匹配期望类型myPetTrait [A]

问题3 - 为什么scala抱怨含糊不清?这可能是因为dogIsPet.type和plantisPet.type属于同一类型&#39;。如何使此代码生效?

感谢

1 个答案:

答案 0 :(得分:0)

我认为您错过了这一点(describe必须a类型Aimplicit合同

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 REPL

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 syntactic sugar

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