2011-07-27 22 views
21

Estoy tratando de crear un rasgo que, cuando se mezcla, reemplazará la definición predeterminada de un método con uno que llame al método original y luego manipule el resultado.Llamar a un método en la superclase en un rasgo auto tipado en scala

Aquí es lo que estoy tratando de hacer:

class Foo { 
    def bar() : String = "Foos bar" 
} 

trait OtherStuff { 
    self : Foo => 
    def bar() : String = self.bar() + " with OtherStuff" 
} 

class Quux extends Foo with OtherStuff 

Si esto funcionaba de la manera que yo quería que, a continuación, volver (new Quux).bar sería ahora Foos bar with OtherStuff. Por desgracia, no funciona de esa manera - lo que consigo es:

<console>:6: error: error overriding method bar in class Foo of type()String; 
method bar in trait OtherStuff of type()String needs `override' modifier 
     class Quux extends Foo with OtherStuff 

Pero si uso override al definir OtherStuff, me sale:

<console>:7: error: method bar overrides nothing 
     override def bar() : String = self.bar() + " with OtherStuff" 

¿Es posible sustituir un método en una auto-tipo usando rasgo? Si no es así, se cambia OtherStuff a ser un rasgo que extends Foo en lugar de uno que tiene un auto tipo de Foo hacer nada malo a todo el código que existe diciendo cosas como

class WhatEver extends Foo with Xyz with Pqr with OtherStuff with Abc 

estoy trabajando en Scala 2.7. 7 porque esta es una regla de compilación sbt, y aún no hemos actualizado nuestro proyecto sbt a las versiones 0.10.x. (Los complementos de los que dependemos no están listos aún)

Respuesta

29

Necesita abstract override y no tiene un tipo de auto para eso.

trait OtherStuff extends Foo {         
    abstract override def bar() = super.bar() + " with OtherStuff" 
} 

Luego class Quux extends Foo with OtherStuff hace lo que quiere.

This article puede ser de su interés.

+3

¿Qué pasa si OtherStuff no es un Foo en mi lógica? ¿No hay otra solución sin extender Foo? ¿O estoy abusando de tipear aquí? – Radian

+0

@Dupont: ¿Por qué debería la clase Quux extender Foo con OtherStuff en lugar de simplemente extender OtherStuff y obtener Foo de la herencia? – polo

0

o se puede hacer una sobrecarga como la siguiente

class Foo { 
    def bar() : String = "Foos bar"} 
trait OtherStuff { 
    self : Foo => 
    def bar(s : String) : String = self.bar() + s} 

class Quux extends Foo with OtherStuff 
(new Quux).bar(" with other stuff") 

lo está, con el tipo de auto anotación, el "otras cosas" se define en otherstuff es parte de Foo cuando el Rasgo se mezcla con Foo, en lugar de una relación de subtipo.

+2

Acabas de definir una función infinitamente recursiva. –

+2

@TonyK .: No, porque la firma de los dos métodos 'bar' es diferente –

Cuestiones relacionadas