Dans TraversableOnce
, il existe une méthode sum
qui est uniquement utilisable si le type contenu est Numeric
(sinon, il ne sera pas compilé). Je me demande si cela est utilisable pour d'autres cas (pour éviter la vérification de l'exécution).Comment effectuer la vérification de type lors de la compilation?
En particulier le cas où nous avons deux traits A et B. Nous voulons avoir une méthode f
qui peut être utilisé que si l'objet hérite à la fois A et B. Mais pas si elle ne couvre que l'un d'entre eux. Je ne veux pas faire un autre trait AB extends A with B
. Je veux juste être incapable d'utiliser f
si les deux traits ne sont pas hérités.
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) }
}
}
EDIT: solution, grâce à Novstrup @ Aaron
trait Bar extends Base { self =>
def f(implicit ev: self.type <:< Foo) = {
//self.asInstanceOf[Foo].g // [1]
ev(this).g // [2]
}
}
Maintenant dans main
, b.f
ne compile pas. Belle
EDIT 2: ligne modifiée [1] [2] refléter les changements dans la réponse par Novstrup @ Aaron
EDIT 3: sans utiliser self
refléter les changements dans la réponse par Novstrup @ Aaron
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
}
}
Vous pouvez également utiliser le paramètre 'ev' pour éviter le cast - c'est un' Function1 [self.type, Foo] '. Mise à jour ma réponse à démontrer. –