Scala中[T]和(o:T)的安装有什么区别?
我看到有两种方法可以在Scala中强制转换对象:Scala中[T]和(o:T)的安装有什么区别?,scala,casting,Scala,Casting,我看到有两种方法可以在Scala中强制转换对象: foo.asInstanceOf[Bar] (foo: Bar) 当我尝试时,我发现asInstanceOf不使用隐式转换,而另一个使用隐式转换 这两种方法在行为上有什么不同?建议在何处使用一个而不是另一个?在Scala中编程在中详细介绍了这一点 基本上,第二种形式可以在模式匹配中使用,提供了isInstanceOf和asInstanceOf功能。比较 if (x.isInstanceOf[String]) { val s = x.asIn
foo.asInstanceOf[Bar]
(foo: Bar)
当我尝试时,我发现asInstanceOf
不使用隐式转换,而另一个使用隐式转换
这两种方法在行为上有什么不同?建议在何处使用一个而不是另一个?在Scala中编程在中详细介绍了这一点 基本上,第二种形式可以在模式匹配中使用,提供了
isInstanceOf
和asInstanceOf
功能。比较
if (x.isInstanceOf[String]) {
val s = x.asInstanceOf[String]
s.length
} else ...
vs
作者暗示,isInstance*
这种冗长的做事方式是有意将您推进模式匹配风格的
但是,我不确定哪种模式对于没有测试的简单类型转换更有效。
是一种类型cast,主要是一种运行时操作。它说应该强迫编译器相信foo.asInstanceOf[Bar]
是一个foo
。如果在运行时将Bar
评估为非foo
,则这可能会导致错误(一个条形图
)ClassCastException
是一种类型归属,它完全是一种编译时操作。这有助于编译器理解代码的含义,而不会强迫它相信任何可能不真实的东西;使用类型属性不会导致运行时失败foo:Bar
implicit def foo(s:String):Int = s.length
// after definition of implicit conversions
implicit def toChild1(p: Parent) : Child1 = new Child1()
implicit def toChild2(p: Parent) : Child2 = new Child2()
(getChild1() : Child2).method2() // OK - implicit conversion to Child2 in ascription
(getChild2() : Child2).method2() // OK - implicit conversion to Child2 in ascription
(getChild2()).method1() // OK - implicit conversion to Child1 when calling method1()
(getChild2()).method2() // OK - implicit conversion to Child2 when calling method2()
(getChild2() : Parent).method() // OK - no implicit conversion
(getChild() : Parent).method1() // OK - implicit conversion to Child1 when calling method()
getChild1().asInstanceOf[Int] // still runtime ClassCastException (no implicit conversion)
然后确保其使用如下:
scala> "hi":Int
res29: Int = 2
将类型Int
归因于String
通常是编译时类型错误,但在放弃之前,编译器将搜索可用的隐式转换以解决问题。将在给定上下文中使用的特定隐式转换在编译时已知
不用说,运行时错误是不受欢迎的,因此以类型安全的方式(不使用
asInstanceof
)指定内容的程度越好!如果你发现自己在使用来代替
,那么你可能应该使用匹配
。Pelotom的回答很好地涵盖了这一理论,下面是一些例子来让它更清楚:
def foo(x: Any) {
println("any")
}
def foo(x: String) {
println("string")
}
def main(args: Array[String]) {
val a: Any = new Object
val s = "string"
foo(a) // any
foo(s) // string
foo(s: Any) // any
foo(a.asInstanceOf[String]) // compiles, but ClassCastException during runtime
foo(a: String) // does not compile, type mismatch
}
如您所见,类型归属可用于解决歧义。有时,编译器无法解决这些问题(请参阅下文),编译器将报告错误,您必须解决它。在其他情况下(如示例中),它只是使用了“错误”的方法,而不是您想要的方法foo(a:String)
未编译,表明类型归属不是强制转换。将其与前一行进行比较,在前一行中,编译器很高兴,但您得到了一个异常,因此将使用类型归属来检测错误
如果您还添加了一个方法,您将得到一个无法解决的歧义
def foo(xs: Any*) {
println("vararg")
}
在这种情况下,foo的第一次和第三次调用将不会编译,因为编译器无法决定是使用单个Any参数调用foo,还是使用varargs调用foo,因为它们似乎都一样好=>必须使用类型归属来帮助编译器
编辑另请参见有一个差异示例:
class Parent() { def method() {} }
class Child1 extends Parent() { def method1() {} }
class Child2 extends Parent() { def method2() {} }
// we return Parent type
def getChild1() : Parent = new Child1()
def getChild2() : Parent = new Child2()
def getChild() : Child1 = new Child1()
(getChild1().asInstanceOf[Child1]).method1() // OK
(getChild1().asInstanceOf[Child2]).method2() // runtime ClassCastException
(getChild1() : Child2).method2() // compile-time error
(getChild2() : Child2).method2() // compile-time error
(getChild() : Parent).method1() // compile-time error
(getChild()).method() // OK
// with asInstanceOf, we can cast to anything without compile-time error
getChild1().asInstanceOf[String] // runtime ClassCastException
getChild1().asInstanceOf[Int] // runtime ClassCastException
我们也可以使用多重分派调用方法:
def prt(p: Parent) = println("parent")
def prt(ch: Child1) = println("child")
prt(new Parent()) // prints "parent"
prt((new Child1()) : Parent) // prints "parent"
prt(new Child1()) // prints "child"
prt(new Parent().asInstanceOf[Child1]) // runtime ClassCastException
prt(new Child1().asInstanceOf[Parent]) // prints "parent"
我们可以定义隐式转换:
implicit def foo(s:String):Int = s.length
// after definition of implicit conversions
implicit def toChild1(p: Parent) : Child1 = new Child1()
implicit def toChild2(p: Parent) : Child2 = new Child2()
(getChild1() : Child2).method2() // OK - implicit conversion to Child2 in ascription
(getChild2() : Child2).method2() // OK - implicit conversion to Child2 in ascription
(getChild2()).method1() // OK - implicit conversion to Child1 when calling method1()
(getChild2()).method2() // OK - implicit conversion to Child2 when calling method2()
(getChild2() : Parent).method() // OK - no implicit conversion
(getChild() : Parent).method1() // OK - implicit conversion to Child1 when calling method()
getChild1().asInstanceOf[Int] // still runtime ClassCastException (no implicit conversion)
需要类型注释的一种情况是,当您想为null指定类型时,例如在使用JavaAPI时。感谢您的精彩解释@佩洛特:嘿,你的例子太棒了!“嗨”:国际。。。我从未见过或使用过这种方式,但这确实是一件有趣的事情。
foo:Bar
被称为类型归属。最好使用这个术语,因为它可以更容易地找到有关它的更多信息。或在搜索时查找此答案。:-)+1至Daniel,用于术语类型归属。否则我不会知道的