I have a base abstract class (trait). It has an abstract method foo(). It is extended and implemented by several derived classes. I want to create a trait that can be mixed into the derived classes so that it implements foo() and then calls the derived class's foo().
Something like:
trait Foo {
def foo()
}
trait M extends Foo {
override def foo() {
println("M")
super.foo()
}
}
class FooImpl1 extends Foo {
override def foo() {
println("Impl")
}
}
class FooImpl2 extends FooImpl1 with M
I tried self types and structural types, but I can't get it to work.
You were very close. Add the abstract modifier to M.foo, and you have the 'Stackable Trait' pattern: http://www.artima.com/scalazine/articles/stackable_trait_pattern.html
trait Foo {
def foo()
}
trait M extends Foo {
abstract override def foo() {println("M"); super.foo()}
}
class FooImpl1 extends Foo {
override def foo() {println("Impl")}
}
class FooImpl2 extends FooImpl1 with M
Related
I have this class defined as follows:
abstract class MyHelper[T, E <: BaseHelper[T]](implicit clsTag: ClassTag[E]) {
val all: Array[E]
def parse(t: T): Try[E] = { ... }
}
and this is how I am using it:
trait IntHelper extends BaseHelper[Int] {}
object MyIntHelper extends MyHelper[Int, IntHelper] { }
How do I simplify MyHelper class definition to accept only the inner generic type T instead of passing two types, E and T?
There's no need for you to directly enforce T in MyHelper since you're only using E itself.
So something like this should be fine.
abstract class MyHelper[E <: BaseHelper[_]](implicit clsTag: ClassTag[E]) {
val all: Array[E]
}
A more fleshed out example looks like:
trait BaseHelper[T] {}
trait IntHelper extends BaseHelper[Int]
abstract class MyHelper[E <: BaseHelper[_]](implicit clsTag: ClassTag[E]) {
val all: Array[E]
}
object MyIntHelper extends MyHelper[IntHelper] {
override val all = Array(new IntHelper{}, new IntHelper{})
}
// just to ensure it works
MyIntHelper.all
So I'm having some trouble with what I think is a pretty simple situation in trait implementation, and I'm hoping there is some simple solution that I'm missing. I'd like to have a method on a trait that accepts as a parameter (and returns as a value only the type of the concrete implementation that it is being called on. Specifically:
trait Foo {
type ConcreteFoo // what to put here?
def combine(that:ConcreteFoo):ConcreteFoo
}
class FooImpl1 extends Foo {
def combine(that:FooImpl1):FooImpl1 = {
// implementation
}
}
class FooImpl2 extends Foo {
def combine(that:FooImpl2):FooImpl2 = {
// implementation
}
}
Right now I have a type Self = FooImpl on the implementing classes, but I'd rather have something on the trait that takes care of it if possible.
This is exactly F-Bounded Polymorphism:
trait Foo[T <: Foo[T]]
def combine(that: T): T
}
class FooImpl1 extends Foo[FooImpl1] {
def combine(that: FooImpl1): FooImpl1 = {
???
}
}
class FooImpl2 extends Foo[FooImpl2] {
def combine(that: FooImpl2): FooImpl2 = {
???
}
}
You can add a type parameter to your trait like this:
trait Foo[A] {
def combine(that: A): A
}
class FooImpl1 extends Foo[FooImpl1] {
override def combine(that: FooImpl1): FooImpl1 = ???
}
class FooImpl2 extends Foo[FooImpl2] {
override def combine(that: FooImpl2): FooImpl2 = ???
}
I have a question concerning Scala override (as my title suggests)
Now I have the following classes/traits:
trait FSM {def transitionGraph:Map[String,(JsValue,FSM)]
abstract class AClass: FSM { def transitionGraph }
class Class extends AClass{ override def transitionGraph ... } <-- Wont work
trait OverrideTrait extends AClass { abstract override def transitionGraph } <-- works
class NewClass extends OverrideTrait { } <--- Works, I can use the overridden transitionGraph
My question is: Why can I not override things from an abstract class. Is it because I am never allowed to instantiate an abstract class. Thus the behavior :
val AClass class = new Class
is never allowed to happen?
Thanks.
There seems to be a lot of stuff omitted from the code you've given, so I'm not sure I get the question, but here's something similar that does compile:
trait FSM { def transitionGraph: String }
abstract class AClass extends FSM { def transitionGraph: String }
class Class extends AClass { override def transitionGraph = ??? }
trait OverrideTrait extends AClass { override def transitionGraph = ??? }
class NewClass extends OverrideTrait { }
Does this help at all?
Your code example wouldn't compile. But it should work once you corrected a few things:
trait FSM {def transitionGraph:Map[String,(JsValue,FSM)]}
abstract class AbstractClass extends FSM { def transitionGraph }
class ConcreteClass extends AbstractClass{ def transitionGraph = ??? }
val someClass: AbstractClass = new ConcreteClass
Given this code: (no matter whether it doesn't make much sense)
object Test {
def main(args: Array[String]) {
(new FooImpl2()).foo()
}
trait Foo {
def foo()
}
trait M extends Foo {
abstract override def foo() {println("M"); super.foo()}
}
abstract class FooImpl1 extends Foo {
}
class FooImpl2 extends FooImpl1 with M{
override def foo() {println("Impl2")}
}
}
At compile time, this error occurs:
error: overriding method foo in trait M of type ()Unit;
method foo needs `abstract override' modifiers
override def foo() {println("Impl2")}
So at this place:
class FooImpl2 extends FooImpl1 with M{
override def foo() {println("Impl2")}
}
Why doesn't override apply on FooImpl1 (in order to provide a concrete implementation for abstract trait method)? It seems like it matches the trait method's instead...and obviously there's a huge conflict with the pattern "abstract override"
M needs to be mixed-in after the concrete def (in linearization order).
I have a class which source I cannot modify:
class Foo {
def bar() = println("bar")
}
And a trait I'd like to mix into it at runtime
trait Zee { this: Foo =>
abstract override def bar() = {
println("before bar")
super.bar()
}
}
This is throwing that bar is not a member of Object with ScalaObject
What am I doing wrong? Is it possible to achieve this without modifying Foo source?
The ultimate client code needs to look like this:
val foo = new Foo with Zee
foo.bar() // should print 'before bar' and then 'bar'
Your Zee trait has no super traits (except implicit inheritance from ScalaObject) thus super does not contain definition for bar and there is nothing to override or call (super.bar).
why don't you write this without self-reference?
class Foo {
def bar() = println("bar")
}
trait Zee extends Foo {
abstract override def bar() = {
println("before bar")
super.bar()
}
}
You can just extends the class Foo in your trait:
trait Zee extends Foo
And your code will work.
your trait needs to extend foo
trait Zee extends Foo {
abstract override def bar() = {
println("before bar")
super.bar()
}
}