gpt4 book ai didi

scala - 为什么更喜欢隐式 val 而不是隐式对象

转载 作者:行者123 更新时间:2023-12-03 21:44:48 24 4
gpt4 key购买 nike

当询问有关隐含的问题时,与答案(或有时就是答案本身)一起给出的常见建议/推荐/建议是使用 implicit vals显式类型签名 而不是使用 implicit objects .
但是,这背后的原因是什么?

最佳答案

“TL;博士;”原因是一个implici val带有显式类型签名的具有您想要的确切类型,而 implicit object有不同的类型。
说明为什么这可能是一个问题的最好方法是用一个简单的例子:

// Having the following definitions.

trait SomeTrait[T] {
def f: T
}

trait ExtendedTrait[T] extends SomeTrait[T] {
def g: T
}

implicit val SomeStringVal: SomeTrait[String] = new SomeTrait[String] {
override def f: String = "from val f"
}

implicit val ExtendedStringVal: ExtendedTrait[String] = new ExtendedTrait[String] {
override def f: String = "from extended val f"
override def g: String = "from extended val g"
}

implicit object ExtendedStringObject extends ExtendedTrait[String] {
override def f: String = "from extended obj f"
override def g: String = "from extended obj g"
}

// What will be the result of:
implicitly[SomeTrait[String]].f
请记住:

If there are several eligible arguments which match the implicit parameter's type, the most specific one will be chosen using the rules of static overloading resolution.


那么,答案是: "from extended obj f" .
上面(有点令人惊讶)的结果,是因为对象有自己的类型(单类型 ExtendedStringObject.typeExtendedTrait[String] 的子类型)引起的,因此,更多的是 “具体”比其他人。
现在,这可能是一个问题的原因是大多数人不知道 object有自己的类型,而且比他们相信的更具体。尽管如此,这也可能使 object在您不希望它被选中时被选中;例如:
// If instead we only had this:

implicit val ExtendedStringVal: ExtendedTrait[String] = new ExtendedTrait[String] {
override def f: String = "from extended val f"
override def g: String = "from extended val g"
}

implicit object ExtendedStringObject extends SomeTrait[String] {
override def f: String = "from extended obj f"
}

// Then what will be the result of:
implicitly[SomeTrait[String]].f
在这种情况下,我们将有一个“模糊的隐含值”异常;因为这两个选项是相同的 具体 .

规则是通用的吗?
不。
与软件工程中的大多数事情一样,没有什么是通用的。
有些情况下使用 implicit val带有显式类型签名的是 not possible (例如,因为即使编译器知道它存在,源代码中的类型也是不可写的)或 it would not produce the correct result whereas an implicit object would do .
一个简单的例子是:
trait A {
type X
}

object A {
type Aux[XX] = A { type X = XX }
}

class B extends A {
type X = T

class T
}

implicit object b extends B
implicit object b1 extends B
这样你就可以要求 implicitly[A.Aux[b.T]]而使用 implicit val b: B = new B {}不会工作。
(代码运行 here 完整上下文 here )。
然而,可以说这些都是罕见的(高级)案例。因此,这可以被视为一个很好的指导方针。

关于scala - 为什么更喜欢隐式 val 而不是隐式对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65258339/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com