为了理解隐含的'在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;。如何使此代码生效?
感谢
答案 0 :(得分: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 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