Reputation: 70267
I have an immutable container-ish class.
class Foo[+T](val arg: T) {
// ...
}
I want to create a subclass of Foo
which has an inner object as its argument.
class Bar extends Foo[this.Inner.type](this.Inner) {
object Inner {
// ...
}
// ...
}
I would like it to be an inner object (and not a separate one) because I do need access to the private data within Bar
. Yet when I try to compile that code, I get:
Example.scala:6: error: this can be used only in a class, object, or
class Bar extends Foo[this.Inner.type](this.Inner) {
^
Example.scala:6: error: this can be used only in a class, object, or template
class Bar extends Foo[this.Inner.type](this.Inner) {template
^
Is it possible to call the superclass constructor using inner objects as arguments? And if so, what am I doing wrong?
EDITED
In response to some comments, I figure I should give a few more specifics. My class Foo
is actually specialized as Foo[+T <: SomeAbstractClass]
and it has several operations defined on it that operate on SomeAbstractClass
instances. I want to create a subclass Bar
which behaves both as a Foo
and its underlying SomeAbstractClass
. Since I can't have Bar
inherit from both classes, I figured an inner object was the next best thing. Really, what I want specifically is a Bar
and an Inner
which behave as a Foo
container and a SomeAbstractClass
element, respectively, and which have complete access to each other's private variables.
Upvotes: 1
Views: 390
Reputation: 70267
wheaties' answer explains why this can't be done the way I wanted to do it, but I figured I would post the solution that got a similar effect for me. I ended up writing an outer class which contains both the Bar
and the Inner
, which can interact freely with the right access modifiers on the variables.
class BarContainer {
object Bar extends Foo[Inner.type](this.Inner) {
// Any private fields should be declared private[BarContainer]
// ...
}
object Inner {
Bar.x = 3
// ...
}
}
Upvotes: 0
Reputation: 35970
What you are trying to do can't be done due to the virtue of the path dependent nature of your inner object
. That is, every time you do the following:
val obj1 = new Bar(...){
def lala(inner: Inner) = ...
}
val obj2 = new Bar(...)
obj1.lala(obj2.Inner) //won't compile!!
the actual Inner
object is redefined. It won't compile because Inner
on obj1
is not the same Inner
on obj2
. They aren't the same type!
Hence, what you are trying to do is reference a definition of something before it can be fully scoped and defined. This is one of the reasons why the compiler is going to complain.
Upvotes: 1