我见过一个implicitly在Scala示例中使用的函数.它是什么,它是如何使用的?
scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: …Run Code Online (Sandbox Code Playgroud) 我知道类型擦除使它们在运行时看起来相同,类型,所以:
class Bar {
def foo[A](xs: A*) { xs.foreach(println) }
def foo[A, B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)) }
}
Run Code Online (Sandbox Code Playgroud)
给出以下编译器错误:
<console>:7: error: double definition:
method foo:[A,B](xs: (A, B)*)Unit and
method foo:[A](xs: A*)Unit at line 6
have same type after erasure: (xs: Seq)Unit
def foo[A,B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)
) }
^
Run Code Online (Sandbox Code Playgroud)
但是有一种简单的方法可以写:
bar.foo(1, 2, 3)
bar.foo(1 -> 2, 3 -> 4)
Run Code Online (Sandbox Code Playgroud)
并让这些调用foo的不同重载版本,而不必明确命名它们:
bar.fooInts(1, 2, …Run Code Online (Sandbox Code Playgroud) 是否可以在Scala中执行以下操作:
class MyTest {
def foo[A <: String _or_ A <: Int](p:List[A]) = {}
}
Run Code Online (Sandbox Code Playgroud)
也就是说,类型A可以是String或Int.这可能吗?
(这里有类似的问题)
我们假设如下:
class Wrapper1 {
case class Condition(test: String)
}
object Wrapper1 extends Wrapper1
class Wrapper2 {
case class Condition[A](test: String)
}
object Wrapper2 extends Wrapper2
class Test
type T = // whatever
def test(fn: T => Wrapper1.Condition): X
def test[R](fn: T => Wrapper2.Condition[R]): X
}
Run Code Online (Sandbox Code Playgroud)
问题是由于类型擦除,这些方法在擦除后具有完全相同的类型.可以很容易地改变第二个的签名:
def test[R](fn: T => Wrapper2.Condition[R])(implicit ev: R =:= R): X
Run Code Online (Sandbox Code Playgroud)
但这会混淆编译器并test在其他地方使用该方法是不可能的.出于多种设计原因,我试图保持这种方法的名称一致.有没有办法成功地做到这一点?
一种通用方法如下:
static <E, K extends E> void someMethod(K k, E[] e) {}
Run Code Online (Sandbox Code Playgroud)
我推测擦除,擦除类型将是:
static void someMethod(Object k, Object[] e) {}
Run Code Online (Sandbox Code Playgroud)
只是好奇类型参数在类型擦除后如何知道约束?那个类型参数K被限制在E?
以下代码无法编译,因为两个乘法运算符在擦除后具有相同的类型:(f: Object)Object
我知道类型擦除,但我见过的所有情况都擦除了泛型类型,如List[Int]或者List[String],在Scala双重定义中回答(2种方法具有相同类型的擦除).
如何让Scala对待不同类型的XxxT`类型不同?
trait AbstractTypes {
type ScalarT
type VectorT
abstract class Operators(u: VectorT) {
def *(f: ScalarT): VectorT
def *(v: VectorT): VectorT
}
}
Run Code Online (Sandbox Code Playgroud) def createFloatBuffer(data: Option[Quaternion]*): Option[FloatBuffer] = data match {
...
}
def createFloatBuffer(data: Option[Vector3f]*): Option[FloatBuffer] = data match {
...
}
Run Code Online (Sandbox Code Playgroud)
由于两种方法具有相同的方法签名,因此不会编译此代码.没有类型不知道调用哪种方法.
我可以重命名方法,但是我想在我的代码中重载样式.
有没有更好的方法来重写这些重载方法来避免这个double definition问题?
def test(a: Option[Int]) {
println(a)
}
def test(a: Option[String]) {
println(a)
}
test(Some(1))
test(Some("1"))
Run Code Online (Sandbox Code Playgroud)