an inheritance question

W

www

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!!
 
I

Ingo R. Homann

Hi,
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?

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
 
L

Lew

www said:
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 ?

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, ...).
 
W

www

Lew said:
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, ...).
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

}
 
W

www

Ingo said:
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 "
".
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.
 
T

Tom Hawtin

www said:
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
 
L

Lew

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

}

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>
 
W

www

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?
 
L

Lew

www said:
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?

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.
 
L

Lew

www said:
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?

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.
 
P

Patricia Shanahan

www said:
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?

Surely that depends on what the common elements are. You have only shown
us what is different between Sub and Sub2.

Patricia
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,173
Latest member
GeraldReund
Top