she*_*lic 4 types scala traits
在TraversableOnce,有一种sum方法只有在包含的类型是Numeric(否则它不会编译)时才可用.我想知道这是否可用于其他情况(以避免运行时检查).
特别的情况下,我们有两个特征A和B.我们希望有一个方法f只能如果对象继承使用两个 A和B.但是,如果它只是扩展不是其中之一.我不想再做一个trait AB extends A with B.我只是希望无法使用,f如果不是两个特征都被继承.
package com.example
trait Base
trait Foo extends Base {
def g = println("foo bar " + toString)
}
trait Bar extends Base {
/* If this is both Foo and Bar, I can do more */
def f = {
if (!this.isInstanceOf[Foo]) error("this is not an instance of Foo")
this.asInstanceOf[Foo].g
}
}
object Test {
def main(args: Array[String]): Unit = {
object ab extends Foo with Bar
object ba extends Bar with Foo
object b extends Bar
ab.f
ba.f
// I don't want next line to compile:
try { b.f } catch { case e: RuntimeException => println(e) }
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:解决方案,感谢@Aaron Novstrup
trait Bar extends Base { self =>
def f(implicit ev: self.type <:< Foo) = {
//self.asInstanceOf[Foo].g // [1]
ev(this).g // [2]
}
}
Run Code Online (Sandbox Code Playgroud)
现在main,b.f不编译.尼斯
编辑2:改变行[1]至[2]反映@Aaron Novstrup的回答变化
编辑3:没有使用self@Aaron Novstrup回答的变化
trait Bar extends Base {
/* If this is both Foo and Bar, I can do more */
def f(implicit ev: this.type <:< Foo) = {
ev(this).g
}
}
Run Code Online (Sandbox Code Playgroud)
是的你可以:
trait A {
def bar = println("I'm an A!")
}
trait B {
def foo(implicit ev: this.type <:< A) = {
ev(this).bar
println("and a B!")
}
}
Run Code Online (Sandbox Code Playgroud)
evidence如果对象的静态类型(在调用站点)扩展,编译器将只能提供参数A.