Hi,
I am puzzled here by an inheritance question:
I have 3 classes:
public Parent {
...
}
public ChildA extends Parent {
...
void doA() {
...
}
}
public ChildB extends Parent {
...
void doB() {
...
}
}
Now, I am trying to use the classes above.
public Base {
protected _person;
...
}
public Sub extends Base {
_person = new ChildA();
_person.doA(); //WRONG !!!! error message: doA() is unresolved
}
I ran into this problem in my real application. What should I do? Some
type casting to force _person as ChildA ?
Thank you!!
Ingo R. Homann - 23 May 2007 15:19 GMT
Hi,
> Hi,
>
[quoted text clipped - 35 lines]
>
> I ran into this problem in my real application. What should I do?
It depends:
(a) doA() only makes sense on Objects of type ChildA. Then use a proper
declaration:
ChildA person=new ChildA();
person.doA();
(b) doA() makes sense on both ChildA and ChildB. Then declare the method
in the superclass "Parent".
(c) doA() makes sense for both classes but should not do anything for
objects of type ChildB. Note that this is a special case of (b) and
should be handled as described above.
(d) Your whole design is broken. Then a quick and dirty solution would
be to do "
> Some
> type casting to force _person as ChildA ?
". But of course the question is: What do you except the program to do
if the variable person indeed refers to an object of type ChildB?
Is an abnormal termination of the program OK for you? (That's why your
design is broken!)
Ciao,
Ingo
www - 23 May 2007 15:36 GMT
> It depends:
>
> (a) doA() only makes sense on Objects of type ChildA. Then use a proper
> declaration:
> ChildA person=new ChildA();
> person.doA();
It is this case. But, I hope to have Base class hold the reference
_person. Because:
public Base {
protected Person _person;
...
}
public Sub extends Base {
_person = new ChildA();
_person.doA(); //WRONG !!!! error message: doA() is unresolved
}
public Sub2 extends Base {
_person = new ChildB();
_person.doB(); //also wrong!!!
}
Otherwise, I would just:
public Sub {
ChildA person = new ChildA();
person.doA();
}
public Sub2 {
ChildB person = new ChildB();
person.doB();
}
> (d) Your whole design is broken. Then a quick and dirty solution would
> be to do "
> > Some
>> type casting to force _person as ChildA ?
> ".
Could you give me more information? My boss gave this layout. I think he
wants me to do downcasting. I googled, but didn't find much direct example.
Thank you.
Lew - 23 May 2007 15:22 GMT
> public Parent {
> ...
[quoted text clipped - 30 lines]
> I ran into this problem in my real application. What should I do? Some
> type casting to force _person as ChildA ?
Would you provide an SSCCE? The code you provided is completely insufficient
to provide any hint as to what your trouble is. For one thing, '_person'
(which by convention should be spelled without underscores) is not declared.
I assume you intended to declare '_person' (whatever type you meant it to be)
protected as an academic exercise; it is rare to have a valid reason for
protected instance variables.
Also, /what/ are your error messages? You should copy and paste error
messages; your paraphrase erases all the important information. The error
message at which you merely hinted is completely unrelated to the errors I can
see in the posted code (undeclared instance variable, '...' not legitimate
syntax, code outside methods and constructors, ...).

Signature
Lew
www - 23 May 2007 15:29 GMT
> Would you provide an SSCCE? The code you provided is completely
> insufficient to provide any hint as to what your trouble is. For one
[quoted text clipped - 10 lines]
> errors I can see in the posted code (undeclared instance variable, '...'
> not legitimate syntax, code outside methods and constructors, ...).
Sorry. I left out "Parent". They should be:
public Base {
protected Parent _person;
...
}
public Sub extends Base {
_person = new ChildA();
_person.doA(); //WRONG !!!! error message: doA() is unresolved
}
Lew - 23 May 2007 15:46 GMT
Lew wrote:
>> Would you provide an SSCCE? The code you provided is completely
>> insufficient to provide any hint as to what your trouble is. For one
>> thing, '_person' (which by convention should be spelled without
>> underscores) is not declared.
> Sorry. I left out "Parent". They should be:
>
[quoted text clipped - 9 lines]
>
> }
This still isn't an SSCCE, and you still haven't provided the error message,
but I see your problem. '_person' (lose the underscore) is of type Person,
which, presumably since you haven't provided an SSCCE, does not have a doA()
method. You cannot call a method not defined for the type of the variable.
Follow Tom's and Patricia's advice. Lose the protected instance variable and
step back from the problem for a broader picture.
Quite often, the process of preparing an SSCCE reveals the answer to your
problem before you even ask for help, and it makes obtaining answers when you
do ask so much more efficient.
First hit off Google for "SSCCE":
<http://mindprod.com/jgloss/sscce.html>
or you can view
<http://www.physci.org/codes/sscce.html>

Signature
Lew
Tom Hawtin - 23 May 2007 15:41 GMT
> I ran into this problem in my real application. What should I do? Some
> type casting to force _person as ChildA ?
The quick fix is:
public abstract class Base {
protected abstract Parent getPerson();
...
}
public Sub extends Base {
private ChildA person = new ChildA();
protected ChildA getPerson() {
return person;
}
...
person.doA();
...
}
But, in general try to avoid elaborate inheritance, in particular the
use of protected.
Tom Hawtin
www - 23 May 2007 15:56 GMT
OK. I just tested and found out: the following works:
public abstract Base {
protected Person _person;
...
}
public Sub extends Base {
_person = new ChildA();
((ChildA)_person).doA(); //working now
}
public Sub2 extends Base {
_person = new ChildB();
((ChildB)_person).doB(); //working now!!
}
Now I am just wondering: with so much extra code due to type casting, is
it worthy to do refactoring?
Lew - 23 May 2007 16:22 GMT
> OK. I just tested and found out: the following works:
>
[quoted text clipped - 19 lines]
> Now I am just wondering: with so much extra code due to type casting, is
> it worthy to do refactoring?
You've hit the nub. All that downcasting is a strong indication that the
model is flawed.
You might model "_person" as a polymorphic instance method instead. Tom's
suggestion is along those lines.
Try thinking more deeply about the underlying object model, which is likely
not yet optimal, as Patricia suggested.
Instead of "doA()" and "doB()", have an overridable method in Person, let's
call it "doX()" for argument. Then you can have something like this:
<example>
abstract class Person
{
public void doX();
}
class ChildA extends Person
{
public void doX()
{
System.out.println( "ChildA.doX()" );
}
}
class ChildB extends Person
{
public void doX()
{
System.out.println( "ChildB.doX()" );
}
}
abstract class Base
{
public Person getPerson();
}
class SubA extends Base
{
ChildA childA = new ChildA();
public Person getPerson()
{
return childA;
}
}
class SubB extends Base
{
ChildB childB = new ChildB();
public Person getPerson()
{
return childB;
}
}
public class TestSubs
{
public static main( String [] args )
{
Base sub = new SubA();
sub.getPerson().doX();
sub = new SubB();
sub.getPerson().doX();
}
}
</example>
This does not depend on the "trick" of returning different subtypes in the
overrides.

Signature
Lew
Lew - 23 May 2007 16:24 GMT
> OK. I just tested and found out: the following works:
>
[quoted text clipped - 19 lines]
> Now I am just wondering: with so much extra code due to type casting, is
> it worthy to do refactoring?
You've hit the nub. All that downcasting is a strong indication that the
model is flawed.
You might model "_person" as a polymorphic instance method instead. Tom's
suggestion is along those lines.
Try thinking more deeply about the underlying object model, which is likely
not yet optimal, as Patricia suggested.
Instead of "doA()" and "doB()", have an overridable method in Person, let's
call it "doX()" for argument. Then you can have something like this:
<example>
abstract class Person
{
public void doX();
}
class ChildA extends Person
{
public void doX()
{
System.out.println( "ChildA.doX()" );
}
}
class ChildB extends Person
{
public void doX()
{
System.out.println( "ChildB.doX()" );
}
}
abstract class Base
{
public Person getPerson();
}
class SubA extends Base
{
ChildA childA = new ChildA();
public Person getPerson()
{
return childA;
}
}
class SubB extends Base
{
ChildB childB = new ChildB();
public Person getPerson()
{
return childB;
}
}
public class TestSubs
{
public static void main( String [] args )
{
Base sub = new SubA();
sub.getPerson().doX();
sub = new SubB();
sub.getPerson().doX();
}
}
</example>
This does not depend on the "trick" of returning different subtypes in the
overrides.

Signature
Lew
Patricia Shanahan - 23 May 2007 16:37 GMT
> OK. I just tested and found out: the following works:
>
[quoted text clipped - 19 lines]
> Now I am just wondering: with so much extra code due to type casting, is
> it worthy to do refactoring?
Surely that depends on what the common elements are. You have only shown
us what is different between Sub and Sub2.
Patricia