scala polymorphism mixins traits

scala - Cómo llamar al método súper al anular un método a través de un rasgo



polymorphism mixins (3)

Aquí está la respuesta que estaba buscando. Gracias a Shadowlands por indicarme la dirección correcta con la función de abstract override de Scala.

trait Abstract extends Result { abstract override def userRepr = "abstract " + super.userRepr } abstract class Result { def userRepr: String = "wtv" } case class ValDefResult(name: String) extends Result { override def userRepr = name } val a = new ValDefResult("asd") with Abstract a.userRepr

El código en vivo está disponible aquí: http://www.scalakata.com/52536cc2e4b0b1a1c4daa4a4

Perdón por el código de ejemplo confuso, estoy escribiendo una biblioteca que se ocupa de Scala AST y no estaba lo suficientemente inspirada para cambiar los nombres.

Parece que es posible cambiar la implementación de un método en una clase con un rasgo como el siguiente:

trait Abstract { self: Result => override def userRepr = "abstract" } abstract class Result { def userRepr: String = "wtv" } case class ValDefResult(name: String) extends Result { override def userRepr = name } val a = new ValDefResult("asd") with Abstract a.userRepr

El código en vivo está disponible aquí: http://www.scalakata.com/52534e2fe4b0b1a1c4daa436

Pero ahora me gustaría llamar a la implementación anterior o super de la función de la siguiente manera:

trait Abstract { self: Result => override def userRepr = "abstract" + self.userRepr }

o

trait Abstract { self: Result => override def userRepr = "abstract" + super.userRepr }

Sin embargo, ninguna de estas alternativas compila. ¿Alguna idea de cómo se podría lograr esto?


No sé si está en condiciones de realizar los siguientes cambios, pero el efecto que desea puede lograrse mediante la introducción de un rasgo adicional (lo llamaré Repr ) y el uso del abstract override en el rasgo del Abstract :

trait Repr { def userRepr: String } abstract class Result extends Repr { def userRepr: String = "wtv" } case class ValDefResult(name: String) extends Result { override def userRepr = name } trait Abstract extends Repr { self: Result => abstract override def userRepr = "abstract-" + super.userRepr // ''super.'' works now }

Tu ejemplo de uso ahora da:

scala> val a = new ValDefResult("asd") with Abstract a: ValDefResult with Abstract = ValDefResult(asd) scala> a.userRepr res3: String = abstract-asd


abstract override es el mecanismo, también conocido como rasgos apilables. Vale la pena agregar que la linealización cuenta, porque eso es lo que determina lo que significa super .

Esta pregunta es una gran adición a las preguntas y respuestas canónicas sobre auto-tipo vs extensión .

Donde la herencia es ambigua con los auto-tipos:

scala> trait Bar { def f: String = "bar" } defined trait Bar scala> trait Foo { _: Bar => override def f = "foo" } defined trait Foo scala> new Foo with Bar { } <console>:44: error: <$anon: Foo with Bar> inherits conflicting members: method f in trait Foo of type => String and method f in trait Bar of type => String (Note: this can be resolved by declaring an override in <$anon: Foo with Bar>.) new Foo with Bar { } ^

Entonces, obviamente, puedes elegir:

scala> new Foo with Bar { override def f = super.f } res5: Foo with Bar = $anon$1@57a68215 scala> .f res6: String = bar scala> new Foo with Bar { override def f = super[Foo].f } res7: Foo with Bar = $anon$1@17c40621 scala> .f res8: String = foo

o

scala> new Bar with Foo {} res9: Bar with Foo = $anon$1@374d9299 scala> .f res10: String = foo