Robin Green
Robin Green

Reputation: 33063

Retaining arguments passed to superclass constructor

In Scala no methods can be invoked on the current instance when the superclass constructor is called. So there is no opportunity for a method to be invoked which will memorise the value that it is returning, in the current instance. How can I retain the arguments produced to give to a superclass constructor, while still using inheritance, as opposed to composition, and without modifying the source code of the class I'm inheriting from?

Upvotes: 1

Views: 317

Answers (4)

Robin Green
Robin Green

Reputation: 33063

In Scala 2.8 and above, use an early definition:

class Foo(arg1: Type1, arg2: Type2) extends {
   val arg3 = new Type3(arg1)
   val arg4 = new Type4(arg2)
} with Bar(arg3, arg4)

This works even if Bar is a class rather than a trait.

Upvotes: 2

Robin Green
Robin Green

Reputation: 33063

Create a companion object with a factory method. The factory method computes the arguments to pass them to the superclass constructor. But it doesn't do so directly, of course - it can't. Instead, it calls your primary constructor, which you can make private, like this:

class C private (private val superclassArg: ArgType) extends Super(superclassArg) { ... }

Unfortunately this solution isn't very compositional, because it doesn't allow you to inherit from C. Making the constructor of C public would, but it would still require duplicating code, and you could forget to preprocess the constructor argument. I suppose it depends whether you think it will always be essential for subclasses of C to preprocess the argument in this way.

Upvotes: 1

Rex Kerr
Rex Kerr

Reputation: 167891

You can also use

class Foo(arg1: Type1, arg2: Type 2)(
  implicit computed: Hidden[(Type3,Type4)] = (new Type3(arg1), new Type4(arg2))
) extends Bar(computed._1, computed._2) { }

given

private[mypackage] class Hidden[A](val value: A) { }
implicit def i_can_hide_things[A](a: A) = new Hidden(a)
implicit def i_can_find_things[A](ha: Hidden[A]) = ha.value

Upvotes: 2

Robin Green
Robin Green

Reputation: 33063

Intersperse another class (here MemoBar) into the inheritance hierarchy, like this:

class Foo(arg1: Type1, arg2: Type2) extends MemoBar(new Type3(arg1), new Type4(arg2)) {
}

class MemoBar(protected val arg3: Type3, arg4: Type4) extends Bar(arg3, arg4) {}

Then your arg3 and arg4 will be retained and visible only to subclasses of MemoBar (in this case, just Foo, but of course you could reuse MemoBar if you faced the same problem with Bar again).

Upvotes: 0

Related Questions