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

2

24

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)

Webber answered 27/7, 2011 at 18:51 Comment(0)
F
34

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.

Freudian answered 27/7, 2011 at 19:2 Comment(2)
What if OtherStuff is not a Foo in my logic ? Isn't there another solution without extendig Foo? Or I am abusing self typing here ?Ingaborg
@Dupont: Why should class Quux extends Foo with OtherStuff rather than just extends OtherStuff and get Foo from inheritance?Dice
E
1

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.

Essex answered 4/3, 2014 at 11:4 Comment(2)
You've just defined an infinitely recursive function.Analogical
@TonyK.: Nope, because the signature of the two bar methods is differentTaveda

© 2022 - 2024 — McMap. All rights reserved.