Como acessar a classe interna “substituída” no Scala?
-
19-09-2019 - |
Pergunta
Tenho duas características, uma estendendo a outra, cada uma com uma classe interna, uma estendendo a outra, com os mesmos nomes:
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
}
Como faço para acessar A.X
aula no C
corpo da classe?Renomeando B.X
não se esconder A.X
não é uma forma preferida.
Para complicar um pouco as coisas, na situação em que encontrei esse problema, as características possuem parâmetros de tipo (não mostrados neste exemplo).
Solução
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
Outras dicas
Para os interessados nesta questão exótica, descobri que ela funciona também como valor de retorno de uma função.Como minhas características A e B possuem parâmetros de tipo, isso deve levar a um código mais conciso:
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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow