Comment accéder à la classe intérieure «remplacée» dans Scala?
-
19-09-2019 - |
Question
J'ai deux traits, l'un étendant l'autre, chacun avec une classe intérieure, l'une étendant l'autre, avec les mêmes noms:
trait A {
class X {
def x() = doSomething()
}
}
trait B extends A {
class X extends super.X {
override def x() = doSomethingElse()
}
}
class C extends B {
val x = new X() // here B.X is instantiated
val y = new A.X() // does not compile
val z = new A.this.X() // does not compile
}
Comment accéder A.X
classe dans le C
Le corps de la classe? Renommée B.X
ne pas se cacher A.X
n'est pas une manière préférée.
Pour rendre les choses un peu compliquées, dans la situation, j'ai rencontré ce problème, les traits ont des paramètres de type (non illustrés dans cet exemple).
La solution
trait A {
class X {
def x() = "A.X"
}
}
trait B extends A {
class X extends super.X {
override def x() = "B.X"
}
}
class C extends B {
val self = this:A
val x = new this.X()
val y = new self.X()
}
scala> val c = new C
c: C = C@1ef4b
scala> c.x.x
res0: java.lang.String = B.X
scala> c.y.x
res1: java.lang.String = A.X
Autres conseils
Pour ceux qui s'intéressent à ce problème exotique, j'ai découvert qu'il fonctionne également comme une valeur de retour d'une fonction. Puisque mes traits A et B ont des paramètres de type, cela devrait conduire à un code plus concis:
trait A[T, U, V] {
class X {
def x() = "A.X"
}
def a = this:A[T, U, V]
}
trait B[T, U, V] extends A[T, U, V] {
class X extends super.X {
override def x() = "B.X"
}
}
class C extends B[SomeClass, SomeOtherClass, ThirdOne] {
val aVerbose = this:A[SomeClass, SomeOtherClass, ThirdOne] // works but is a bit ugly
val aConcise = a
val x = new this.X()
val y = new aVerbose.X()
val z = new aConcise.X()
}
scala> val c = new C()
c: C = C@1e852be
scala> c.x.x()
res2: java.lang.String = B.X
scala> c.y.x()
res3: java.lang.String = A.X
scala> c.z.x()
res4: java.lang.String = A.X
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow