В 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) }
}
}
РЕДАКТИРОВАТЬ: решение, благодаря @ Аарон Новструп
trait Bar extends Base { self =>
def f(implicit ev: self.type <:< Foo) = {
//self.asInstanceOf[Foo].g // [1]
ev(this).g // [2]
}
}
Теперь в main
, b.f
не компилируется. Nice
РЕДАКТИРОВАТЬ 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
}
}