views:

132

answers:

1

Suppose I have the following class heirarchy:

class A()
class B(a:A)
class C(b:B)

class BaseClass(b:B, c:C)

Now I want to implement a subclass of BaseClass, which is given an instance of A, and constructs instances of B and C, which it passes to its superclass constructor.

If I could use arbitrary expressions, I'd do something like this:

b = new B(a)
c = new C(b)
super(b, c)

Because the second argument to the parent constructor depends on the value of the first argument, though, I can't see any way to do this, without using a factory function, or a gratuitous hack, such as :

class IntermediateSubclass(b:B) extends BaseClass(b, new C(b))
class RealSubclass(a:A) extends IntermediateSubclass(new B(a))

Is there clean way to do this?

+5  A: 

Probably the best way to handle this sort of situation is by writing a factory method in the companion object for the subclass of BaseClass you want to write.

class A()
class B(a:A)
class C(b:B)

class BaseClass(b:B, c:C)

class SBC private (a: A, b: B, c: C)
extends BaseClass(b, c)

object SBC
{
    def
    apply(a: A): SBC = {
        val b = new B(a)
        val c = new C(b)
        new SBC(a, b, c)
    }
}

You can make any of those constructor parameters into fields without affecting anything (by prefixing with val, if you're not familiar with that syntax):

class A()
class B(val a: A)
class C(val b: B)

class BaseClass(val b: B, val c: C)

class SBC private (val a: A, b: B, c: C)
extends BaseClass(b, c)

object SBC
{
    def
    apply(a: A): SBC = {
        val b = new B(a)
        val c = new C(b)
        new SBC(a, b, c)
    }
}

Now new instances of SBC can be created with this sort of expression: SBC(aValue) (regardless of whether the vals are used).

scala> val a1 = new A
a1: A = A@14a8f44

scala> val sbc1 = SBC(a1)
sbc1: SBC = SBC@7d8bb

scala> sbc1.a
res0: A = A@14a8f44

scala> sbc1.b
res1: B = B@c7272

scala> sbc1.c
res2: C = C@178743b
Randall Schulz
I'd forgotten about the apply method - thanks for the reminder.
Nick Johnson