Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a method on the superclass in a self-typed trait in scala

I'm trying to create a trait that, when mixed in, will replace the default definition of a method with one that calls the original method and then manipulates the result.

Here's what I'm trying to do:

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

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

class Quux extends Foo with OtherStuff

If this worked the way I wanted it to, then (new Quux).bar would now return Foos bar with OtherStuff. Unfortunately, it doesn't work that way - what I get is:

<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

But if I use override when defining OtherStuff, I get:

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

Is it possible to override a method in a self-type using trait? If not, will changing OtherStuff to be a trait that extends Foo instead of one that has a self-type of Foo do anything bad to all the code that exists saying things like

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

I'm working in scala 2.7.7 because this is an sbt build rule, and we haven't upgraded our sbt project to the 0.10.x versions yet. (Plugins we depend on aren't ready yet)

like image 349
Daniel Martin Avatar asked Jul 27 '11 18:07

Daniel Martin


2 Answers

You need abstract override and no self type for that.

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

Then class Quux extends Foo with OtherStuff does what you want.

This article might be of interest.

like image 157
Didier Dupont Avatar answered Sep 30 '22 17:09

Didier Dupont


or you can do a overloading like the following

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")

the thing is, with self type annotation, the "other stuff" defined in OtherStuff is part of Foo when the Trait is mixed with Foo, rather than a sub-type relationship.

like image 42
Haiyuan Zhang Avatar answered Sep 30 '22 17:09

Haiyuan Zhang