Inheritance Question

J

jsguru72

I have a question about inheritance and member variables.

Please consider the following classes.

//Parent Abstract Class
public abstract class Fruit {
protected String fruit = "Fruit";

public String whatAmI() {
return fruit;
}
}


//Subclass
public class Apple extends Fruit {
protected String fruit = "Apple";

public Apple() {
}

public static void main(String [] args) {
Apple myApple = new Apple();

System.out.println("-->" + myApple.whatAmI() );
}
}

No matter how I try to set the fruit variable in the subclass, it
always prints out the value in the parent class.

This is just an example of the problem I am having. In my actual
environment, the whatAmI() method is much more involved. The Fruit
class will end up having as many as 50 classes that extend it. I want
to avoid having to override whatAmI() in every one of those subclasses
since 99% of the code is the same except for the value of the
variable.

I think I can understand that the whatAmI() method can only see the
fruit variable in the parent, but is there any way to set this up so
that the whatAmI() method uses the value of the fruit variable as
defined in the Apple class?

I.E. Short of overriding whatAmI() in each child class, what can I do
to get this program to output 'Apple' instead of 'Fruit'?


Thanks,
John S.
 
J

Joshua Cranmer

jsguru72 said:
I have a question about inheritance and member variables.

Please consider the following classes.

//Parent Abstract Class
public abstract class Fruit {
protected String fruit = "Fruit";

public String whatAmI() {
return fruit;
}
}


//Subclass
public class Apple extends Fruit {
protected String fruit = "Apple";

public Apple() {
}

public static void main(String [] args) {
Apple myApple = new Apple();

System.out.println("-->" + myApple.whatAmI() );
}
}

No matter how I try to set the fruit variable in the subclass, it
always prints out the value in the parent class.

As it should. Access of field variables are not dynamically-dispatched,
like methods.
I think I can understand that the whatAmI() method can only see the
fruit variable in the parent, but is there any way to set this up so
that the whatAmI() method uses the value of the fruit variable as
defined in the Apple class?

Short of reflection, or overriding, no.
I.E. Short of overriding whatAmI() in each child class, what can I do
to get this program to output 'Apple' instead of 'Fruit'?

This is how I do it:

public abstract class Fruit {
protected Fruit(String type) {
this.type = type;
}

public String whatAmI() {
return this.type;
}
}

public class Apple extends Fruit {
public Apple() {
super("Apple");
}
}

Alternatively, you could define whatAmI() as follows:

public String whatAmI() {
return this.getClass().getName();
}
 
J

jsguru72

Thanks for your reply. After posting, I did additional testing and
came up with a solution that seems to work. It is similar to what you
provided Joshua.

I simply added an accessor method to the abstract class and then I
override it in the child class.

//Parent Class
public abstract class Fruit {
protected String fruit = "Fruit";

public String getFruit() { //<------New accessor method
return fruit;
}

public String whatAmI() {
return getFruit(); //<------Reference accessor instead of
variable
}
}


//Subclass
public class Apple extends Fruit {
protected String fruit = "Apple";

public String getFruit() { //<------Override only the accessor
method.
return fruit;
}

public static void main(String [] args) {
Apple myApple = new Apple();

System.out.println("-->" + myApple.whatAmI() );
}
}


Now the program outputs 'Apple' as needed. I also tested this in my
actual program and it is working fine.

Thank you.
 
D

Daniele Futtorovic

Thanks for your reply. After posting, I did additional testing and
came up with a solution that seems to work. It is similar to what you
provided Joshua.


> This is how I do it:
>
> public abstract class Fruit {
>
> private String type;
>
> protected Fruit(String type) {
> this.type = type;
> }
>
> public String whatAmI() {
> return this.type;
> }
> }
>
public class Apple extends Fruit {
public Apple() {
super("Apple");
}
}


Alternatively...
<code>
//Parent Abstract Class
public abstract class Fruit {
protected String fruit = "Fruit";

public String whatAmI() {
return fruit;
}
}


//Subclass
public class Apple extends Fruit {
public Apple() {
fruit = "Apple";
}

public static void main(String [] args) {
Apple myApple = new Apple();

System.out.println("-->" + myApple.whatAmI() );
}
}
</code>

....would work, too. It's not very clean, however.

What Joshua wrote is "how I do it".
 
A

Arne Vajhøj

Daniele said:
Thanks for your reply. After posting, I did additional testing and
came up with a solution that seems to work. It is similar to what you
provided Joshua.

This is how I do it:

public abstract class Fruit {

private String type;

protected Fruit(String type) {
this.type = type;
}

public String whatAmI() {
return this.type;
}
}

public class Apple extends Fruit {
public Apple() {
super("Apple");
}
}


Alternatively...
<code>
//Parent Abstract Class
public abstract class Fruit {
protected String fruit = "Fruit";

public String whatAmI() {
return fruit;
}
}


//Subclass
public class Apple extends Fruit {
public Apple() {
fruit = "Apple";
}

public static void main(String [] args) {
Apple myApple = new Apple();

System.out.println("-->" + myApple.whatAmI() );
}
}
</code>

...would work, too. It's not very clean, however.

It certainly is not very clean.

The sub class could forget to set the protected field.

The constructor method forces the sub class to specify a name.

Arne
 
D

Daniele Futtorovic

Daniele said:
Alternatively...
<code>
//Parent Abstract Class
public abstract class Fruit {
protected String fruit = "Fruit";

public String whatAmI() {
return fruit;
}
}


//Subclass
public class Apple extends Fruit {
public Apple() {
fruit = "Apple";
}

public static void main(String [] args) {
Apple myApple = new Apple();

System.out.println("-->" + myApple.whatAmI() );
}
}
</code>

...would work, too. It's not very clean, however.

It certainly is not very clean.

Most definitely. But since I seemed as though the OP's problem was that
he didn't understand he was shadowing the superclass field, I thought
I'd mention it, showing how the field could be accessed.
 
T

Tom Anderson

Daniele said:
Alternatively...
<code>
//Parent Abstract Class
public abstract class Fruit {
protected String fruit = "Fruit";

public String whatAmI() {
return fruit;
}
}


//Subclass
public class Apple extends Fruit {
public Apple() {
fruit = "Apple";
}

public static void main(String [] args) {
Apple myApple = new Apple();

System.out.println("-->" + myApple.whatAmI() );
}
}
</code>

...would work, too. It's not very clean, however.

It certainly is not very clean.

Most definitely. But since I seemed as though the OP's problem was that
he didn't understand he was shadowing the superclass field, I thought
I'd mention it, showing how the field could be accessed.

I agree. Whilst the approach the OP was trying to take is not the best,
i'm pretty sure the real problem he had was that he didn't realise that
one field declaration was shadowing the other.

tom
 

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,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top