在scala源代码中我可以看到这段代码:
@implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
// not in the <:< companion object because it is also
// intended to subsume identity (which is no longer implicit)
implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
@implicitNotFound(msg = "Cannot prove that ${From} =:= ${To}.")
sealed abstract class =:=[From, To] extends (From => To) with Serializable
private[this] final val singleton_=:= = new =:=[Any,Any] { def apply(x: Any): Any = x }
object =:= {
implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A]
}
Run Code Online (Sandbox Code Playgroud)
我并不完全清楚为什么这两个类都会扩展Function1.不会扩展任何东西吗?
大多数情况下,当您想要确保A <:< B(或者更准确地说,您希望确保A <: B使用类型的证据A <:< B)时,这是因为您实际上具有类型的值A并且希望能够将其视为类型的实例B.
当你有一个值时x: A,通过存在A一个子类型的隐式值证明B不会神奇地改变xto 的类型B.
但是对于所有意图和目的<:<实际上允许这个,因为它也是一个只返回其参数的函数(它基本上是身份,只有一个添加 - 并稍微隐藏 - 演员).当你的方法获得通过类型的隐含价值通过这种方式A <:< B,你得到的是居然还从合适的隐式转换A到B(隐式转换x:A到类型的值B).
在你实际上并不需要转换任何东西的情况下,无论是否<:<扩展都无关紧要 Function1.
同样的理由适用于=:=.
更新:响应"在= = =的情况下,为什么我要将类型A的值转换为类型A的值?":
你应该首先注意,即使在<:<存在相同的明显矛盾的情况下:当然,如果A <: B我可以将任何类型A的值视为类型的值B(这几乎是子类型的定义).假设我们有以下通用方法:
class Foo {
def hello() { println("hello!") }
}
def f[T]( value: T )(implicit e: T <:< Foo){
value.hello()
}
class Bar extends Foo
f( new Bar )
Run Code Online (Sandbox Code Playgroud)
编译编译f器时只知道它value有某种类型T.没有什么能告诉编译器T永远是子类型的Foo.所以,如果不是因为这样的事实e: T <:< Foo也提供了从隐式转换T到Foo,则调用value.hello()将失败,因为T仅仅是某种类型的编译器不知道任何有关.只有通过精心设计才能e: T <:< Foo在范围内具有隐含值,当且仅当T <: Foo.但编译器并不知道这一点,所以从他的观点来看T并且Foo是无关的.因此,我们必须为他提供一种方法来将类型的值转换T为Foo,这由T <:< Foo证据本身完成.
正如我所说,同样的理由适用于=:=:有一个实例T =:= Foo不会给编译器提供关于这样一个事实的线索T = Foo,因此必须向他提供转换.
| 归档时间: |
|
| 查看次数: |
189 次 |
| 最近记录: |