0

Look at this example:

class Outer(private val handler: Actor){
  def this() = this(new Handler)  // type Handler not found ? ?

 class Handler extends Actor{
    override  def act() {

    }
  }
}

The compiler complain that class Handler is not found. Is this a bug ?

爱国者
  • 4,298
  • 9
  • 47
  • 66

2 Answers2

4

The inner class Handler has a reference on the outer class instance, and you're trying to create a new Handler before the outer instance exists — which is impossible.

You can try something like this instead:

class Outer(h: Actor = null) {

  private val handler =
    if (h != null) h
    else new Handler

  class Handler extends Actor {
    override def act() {

    }
  }
}

If you're worried about using null, you can use the solution described here to replace null in default values for parameters.

Community
  • 1
  • 1
Jean-Philippe Pellet
  • 59,296
  • 21
  • 173
  • 234
2

First of all you probably know that access to inner classes is via the dot (.) operator. So accessing the Handler class should be Outer.Handler. When you're in scope this the compiler cannot locate the Handler class, because the inner class is tied to the outer object. Everything is explained much better here: http://www.scala-lang.org/node/115. In short you get a quite impossible situation, because the inner class is hidden inside the outer class, but an actual instantiation of the outer class requires the inner class...

There are many ways to solve it I guess, I'll just quickly sketch one here. Since you probably want the Handler class to be tied to Outer in some way, I'd recommend creating and object and then calling the Outer class from here. Thus you'd get roughly the same syntax and everything is stored in one place. It could look something like this:

class Outer(private val handler : Actor)

object Outer {
  class Handler extends Actor { override def act { } } // The "inner" class
  def apply() = new Outer(new Handler)
  def apply(handler : Actor) = new Outer(handler)
}

Hope that helps :)

Jens Egholm
  • 2,730
  • 3
  • 22
  • 35
  • You can only write `Outer.Handler` if `Handler` is defined in the object `Outer`, and thus has no reference to the instance of an actual outer object. You're changing the semantics of the OP. – Jean-Philippe Pellet Nov 27 '11 at 11:23
  • Erm I'm not really sure what you mean. My point is that I think it's easier to change the structure to create the outer object instead of inferring the outer object. To me it's just more clean. Especially if I can avoid mutable structures. – Jens Egholm Nov 27 '11 at 20:04
  • Your `Handler` class has no reference to the outer object, therefore, even if it may look cleaner to you, you're changing the semantics intended by the OP. My solution doesn't (and doesn't use mutable structures either). – Jean-Philippe Pellet Nov 29 '11 at 08:40