0

So here is the problematic code:

trait World {
  type State
  def dynamics(s: State): State
  // ...
}
trait GridWorld extends World {
  class State {...} // concrete
  def dynamics(s: State) = s    // concrete
  // some other staff still abstract
}
trait SimpleGridWorld extends GridWorld {
  class State extends super.State {...}  // concrete
  def foo {dynamics(new State)}  // compiler error
}

The compiler says that, dynamics in both World and GridWorld match the signature. However, in World it is abstract and then implemented in GridWorld, so it seems to me that it is clear that I am calling GridWorld.this.dynamics.

Another thing I noticed is that, if I remove the extends super.State in SimpleGridWorld, everything works fine (which I don't understand why, and I do need the functionalities defined in GridWorld.State here). Any explanations? Thanks!

UPDATE Anyway I am seeing my design pattern quite weird, since if State in SimpleGridWorld does not inherit GridWorld.this.State, dynamics would refer to the unimplemented one defined in the root trait World (which makes sense because the implementation in GridWorld may use the functionalities of GridWorld.this.State which may not exist in SimpleGridWorld.this.State). But what I want is:

  1. XXXWorld.this.State must inherit its super.State (or just use it)
  2. dynamics always refers to super.dynamics if implemented in the super trait/class unless overrided here.

How can I do this? I think it is not a totally irrelevant question, and probably the answer to the previous one would tell me how to redesign my pattern.

Kane
  • 1,314
  • 2
  • 9
  • 14

1 Answers1

1

How about:

trait World {
  type State
  def dynamics(s: State): State
}
trait GridWorld extends World {
  type State = MyState
  class MyState {} // concrete
  def dynamics(s: State) = s    // concrete
}
trait SimpleGridWorld extends GridWorld {
  class MyState extends super.MyState {}  // concrete
  def foo {dynamics(new MyState)}  // compiler error; ok
}
som-snytt
  • 39,429
  • 2
  • 47
  • 129
  • Thanks for the reply, but why still compiler error? I tried it and it seems working, despite that I don't think `MyState` and `State` should ever have separate meanings conceptually. – Kane Dec 13 '12 at 19:44
  • Hmm, I think about it more and find that there is something thoughtful in your solution. `GridWorld` is very special in the type hierarchy as from there, subclasses no longer have `State==MyState`. This makes some sense because `GridWorld` is the place where `dynamics` is implemented. As long as I do not override `dynamics` in later classes (which I thought of but maybe should not do so), everything works fine and is meaningful. – Kane Dec 13 '12 at 20:10
  • 1
    you might want to consider something similar to this [Tour of Scala](http://www.scala-lang.org/node/124) article and use `type State <: StateIf` and then define an interface bass class `abstract class StateIf` – David Holbrook Dec 13 '12 at 20:56
  • This is one of my favorites: http://stackoverflow.com/questions/10213395/cake-pattern-with-overriding-abstract-type-dont-work-with-upper-type-bounds – som-snytt Dec 14 '12 at 01:28