Chapter 6, Exercise 2
Larry Clapp kindly resolved a couple of mysteries,
including my inaccurate guess that CLAPP was an acronym,
and the discrepancies in the TiJ versions that we each
have. (I have the PDF of the 3rd ed., Revision 4.0);
Larry was using the 2nd Edition (hardcopy), ISBN 0-13-027363-5.
For last week's exercise (c6x1), I suppose an implicit part of
the exercise (where it says to "observe") would be to write something
about what I observed. Namely, that the system, in effect,
generated a constructor for C, consisting of the compiler-generated
initialization of the base class "A" part of C, and the body
part of C, where I wrote the "new B" call that initialized the
obj_b member.
Anyway, Exercise 2: Modify Exercise 1 so that A and B have constructors with
arguments instead of default constructors. Write a constructor
for C and perform all initialization within Cs constructor.
Hmmm, I don't see that it is possible to have those new
constructors be
"instead" of the default constructor. Similarly, I don't
see a way to declare the default constructor to be private.
I made this one kinda verbose, to see what was going on.
Here is Larry's Java solution.
package x;
class A {
var mi : Int = _;
def this ( ci: Int ) = {
this();
W.rn( "A constructor called with " + ci);
mi = ci;
}
def see = W.rn( "A.mi = " + mi );
def see2 = W.rn( "A.mi = " + mi );
}
class B {
var mj : Int = _;
def this ( cj: Int ) = {
this();
W.rn( "B constructor called with " + cj);
mj = cj;
}
def see = W.rn( "B.mj = " + mj );
}
class C extends A {
var mk : Int = _;
var obj_b : B = _;
def this ( cboth : Int ) = {
this( cboth, cboth );
}
def this ( ca : Int, cb : Int ) = {
this();
mi = ca; /* Can't figure out how to call super(ca) */
obj_b = new B( cb );
mk = ca + cb;
}
override def see = {
// this.asInstanceOf[A] see; // Got a stack overflow
this see2;
W.r( "C.mk = " + mk + "; " );
if (obj_b == null) {
W.rn( "C.B is null." );
}
else {
W.rn( "C.B.mj = " + obj_b.mj );
}
}
}
object c6x2 {
def main ( args : Array[String] ) = {
val obj_c0 = new C();
val obj_c1 = new C( 42 );
val obj_c2 = new C( 12, 21);
W.rn( "obj_c0:" ); obj_c0 see;
W.rn( "obj_c1:" ); obj_c1 see;
W.rn( "obj_c2:" ); obj_c2 see;
}
}
I'm sure there must be a simple way to call the
base class "see" method, but I couldn't find it in
the short time I've allowed myself for this one.
Oh, and in case you missed it, here's my output
shorthand module, W.scala:
package x;
object W {
def r ( s: String ) = Console.print( s );
def rn ( s: String ) = Console.println( s );
}
Here's what the output is for me tonight:
B constructor called with 42
B constructor called with 21
obj_c0:
A.mi = 0
C.mk = 0; C.B is null.
obj_c1:
A.mi = 42
C.mk = 84; C.B.mj = 42
obj_c2:
A.mi = 12
C.mk = 33; C.B.mj = 21
11:56:02 PM