Cannot override protected fields

I know this is not possible, but my question is why did they design it

that way:

public class ParentForm {

protected String name = "ParentForm";

protected String getName(){return name;}

}

public class ChildForm extends ParentForm{

protected String name = "ChildForm"; //I am trying to override

the field value but reuse the method from parent.

}

public class Test {

public static void main(String[] args) {

System.out.println((new ParentForm()).getName());

System.out.println((new ChildForm()).getName());

}

}

Output:

ParentForm

ParentForm

I wanted to see "ChildForm" in the second line. Why do I have to

duplicate (literally cut and paste) the getName() method in the child

to achieve it ?

Can someone explain the concept I am missing ?

[898 byte] By [deepinjavaa] at [2007-11-27 7:51:28]
# 1

Member variables are not runtime polymorphic.

When you refer to a member variable through someReference.someVaraible, which class' variable is determined at compile time by the type of someReference. In your case, someReference is this. Since this is a reference to the parent class, it only knows about the parent's variables.

The only thing that gets resolved at runtime is which class' version of a non-static, non-private method to invoke.

jverda at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 2
Why not just use getClass().getName()?
Hippolytea at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 3
By the way, having same-named protected variables in parent and child is a rather smelly design.
jverda at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 4

"Member variables are not runtime polymorphic."

I understand the fact, but cannot justify it.

Wouldn't it be good have the privilege of saying, "I am extending your class wherein I want to inherit everything from you except override the value of this one field" ? But currently that is not possible unless I write a dummy METHOD that looks exactly like the parent (when I do that, it will implicitly access its local field).

Was it an intentional design ?

deepinjavaa at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 5

> Wouldn't it be good have the privilege of saying, "I

> am extending your class wherein I want to inherit

> everything from you except override the value of this

> one field" ?

I've never encountered a situation where that would be useful.

> Was it an intentional design ?

I'm quite certain it was. That's not the kind of thing you do by accident.

jverda at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 6

ParentForm pF = new ParentForm();

ChildForm cF = new ChildForm();

System.out.println(cF.getName() + " (vs) " + cF.getClass().getName());

Output:

ParentForm (vs) ChildForm

Same question - what was their reasoning in designing it that way ? Why not allow cF.getName() to return "ChildForm" ?

[Thanks for your replies so far]

deepinjavaa at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 7
> Same question - what was their reasoning in designing it that way ? Why not allow cF.getName() to return "ChildForm" ?The problem with your line of questioning is that you've written someatrocious code and you keep asking why doesn't it work?
Hippolytea at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 8

You aren't overriding the name variable, you're shadowing it. ChildForm doesn't touch the ParentForm's name variable since it declares it's own. So instead of declaring another protected String name = "...", just change the value of it.

public class ChildForm extends ParentForm {

public ChildForm() {

name = "ChildForm"; //I am trying to override the field value but reuse the method from parent.

}

}

hunter9000a at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 9

> > Wouldn't it be good have the privilege of saying,

> "I

> > am extending your class wherein I want to inherit

> > everything from you except override the value of

> this

> > one field" ?

>

> I've never encountered a situation where that would

> be useful.

Well, it will surely save a lot of unnecessary coding writing dummy methods.

deepinjavaa at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 10

Or even...

class ParentForm {

String name;

public String getName() {

return name;

}

public ParentForm(String name) {

this.name = name;

}

}

public class ChildForm extends ParentForm {

public ChildForm() {

super("ChildForm");

}

}

kevjavaa at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 11

> > > Wouldn't it be good have the privilege of

> saying,

> > "I

> > > am extending your class wherein I want to

> inherit

> > > everything from you except override the value of

> > this

> > > one field" ?

> >

> > I've never encountered a situation where that

> would

> > be useful.

>

> Well, it will surely save a lot of unnecessary coding

> writing dummy methods.

I've never had to write dummy methods.

Like I said, I think the real problem is in your design.

jverda at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 12

> class ParentForm {

>String name;

> public String getName() {

>return name;

>

>public ParentForm(String name) {

>this.name = name;

> }

> }

>

> public class ChildForm extends ParentForm {

>public ChildForm() {

>super("ChildForm");

> }

> }

And add this into ParentForm?

public ParentForm() {

this("ParentForm");

}

Hippolytea at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 13
> And add this into ParentForm?> public ParentForm() {>this("ParentForm");> }Indeed, thanks... :)
kevjavaa at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 14
And editpublic ParentForm(String name) {...to make it protected? I'll stop now :-)
Hippolytea at 2007-7-12 19:32:35 > top of Java-index,Java Essentials,Java Programming...
# 15
> And edit> public ParentForm(String name) {...> to make it protected? That would tighten things up a bit, wouldn't it? No, need to stop now, you're on a roll!
kevjavaa at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 16

> > And edit

> > public ParentForm(String name) {...

> > to make it protected?

>

> That would tighten things up a bit, wouldn't it?

> No, need to stop now, you're on a roll!

And the field should probably be final, though without knowing the OP's real requirements, that's just a guess.

jverda at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 17
> And the field should probably be final, though> without knowing the OP's real requirements, that's> just a guess.Sweet... I'm going to have to start putting more "example" code up here for review... :-)
kevjavaa at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 18

> > > > Wouldn't it be good have the privilege of

> > saying,

> > > "I

> > > > am extending your class wherein I want to

> > inherit

> > > > everything from you except override the value

> of

> > > this

> > > > one field" ?

> > >

> > > I've never encountered a situation where that

> > would

> > > be useful.

> >

> > Well, it will surely save a lot of unnecessary

> coding

> > writing dummy methods.

>

> I've never had to write dummy methods.

>

> Like I said, I think the real problem is in your

> design.

To elaborate...

There's a single object. It has variables to represnt its state. Two non-private variables of the same name is confusing. You're saying "this object's foo is bar, but this object's foo is also baz."

If there really are two different quantiies, the variables should be named differently. If there's only a single quantity, then there should be one variable and maybe how it's set/gotten would be overridden in the appropriate methods.

I don't think I've ever even had a use for a protected variable that's not final. This is another design smell. If the child is modifying state that's declared in the parent, the variable should be private and there should be a protected setter method.

jverda at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 19

> You aren't overriding the name variable, you're

> shadowing it. ChildForm doesn't touch the

> ParentForm's name variable since it declares it's

> own. So instead of declaring another protected String

> name = "...", just change the value of it.

>

> [code]public class ChildForm extends ParentForm {

>public ChildForm() {

> name = "ChildForm"; //I am trying to override the

> field value but reuse the method from parent.

>}

> ode]

Thanks for the reply. And I understand there are different ways to get this done. I just wanted to understand the concept or reasoning behind this behaviour which is only with fields - not methods.

When we redeclare a variable in the child, it "shadows" it. But when we redeclare a method in the child, it overrides it. I understand the fact and the design. What I don't understand is why they have chosen to treat child variables differently from child methods ?

deepinjavaa at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 20

> Thanks for the reply. And I understand there are

> different ways to get this done. I just wanted to

> understand the concept or reasoning behind this

> behaviour which is only with fields - not methods.

>

> When we redeclare a variable in the child, it

> "shadows" it. But when we redeclare a method in the

> child, it overrides it. I understand the fact and the

> design. What I don't understand is why they have

> chosen to treat child variables differently from

> child methods ?

You can think of it conceptually like this: When you declare a method or field in a child class, you're making a different version of it. If you don't declare a new version in the child, then the parent's version will be inherited. In your original code, you created a new variable, so if you referenced it from the child class you'd get the child's version. But you didn't access it from the child class, you only accessed it through the method in the parent class. If you had overridden the method also, it would have accessed the child's version of name:

package sandbox;

class ParentForm {

protected String name = "ParentForm";

protected String getName(){return name;} // this method accessed parent's version of name

}

class ChildForm extends ParentForm{

protected String name = "ChildForm"; //I am trying to override the field value but reuse the method from parent.

protected String getName(){return name;}// this method access Child's version of name

}

public class Test {

public static void main(String[] args) {

System.out.println((new ParentForm()).getName());

System.out.println((new ChildForm()).getName());

}

}

Output:

ParentForm

ChildForm

It's a lot like when you shadow a class member inside a method:

public class Test {

private int i = 0;

public void method(int i) {

System.out.println(i);

}

public static void main (String[] args) {

new Test().method(5);

}

}

That method prints 5 because it's using the version of i that's declared in the method, not the class member, because the class member is shadowed.

hunter9000a at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 21

> You can think of it conceptually like this: When you

> declare a method or field in a child class, you're

> making a different version of it. If you don't

> declare a new version in the child, then the parent's

> version will be inherited. In your original code, you

> created a new variable, so if you referenced it from

> the child class you'd get the child's version. But

> you didn't access it from the child class, you only

> accessed it through the method in the parent class.

> If you had overridden the method also, it would have

> accessed the child's version of name:

Ok, I think understand where you're coming from. Looking at it this way helps. Thanks a lot !

deepinjavaa at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 22

> You can think of it conceptually like this: When you

> declare a method or field in a child class, you're

> making a different version of it. If you don't

> declare a new version in the child, then the parent's

> version will be inherited. In your original code, you

> created a new variable, so if you referenced it from

> the child class you'd get the child's version. But

> you didn't access it from the child class, you only

> accessed it through the method in the parent class.

> If you had overridden the method also, it would have

> accessed the child's version of name:

> [code]package sandbox;

>

But wait - by the same line of reasoning, can you explain this output :

<snip>

ParentForm pF = new ParentForm();

ChildForm cF = new ChildForm();

System.out.println("Here: " + cF.getName() + " (vs) " + cF.getClass().getName());

<snip>

Gives Output:

Here: ParentForm (vs) ChildForm

Can you please explain the above output in the same way ? thanks.

deepinjavaa at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 23
> Can you please explain the above output in the same> way ? thanks.Not without knowing which version of those classes you're using. :)
hunter9000a at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 24

Ok, here is the code for clarity:

public class ParentForm {

protected String name = "ParentForm";

protected String getName(){return name;}

}

public class ChildForm extends ParentForm{

protected String name = "ChildForm"; //I am trying to override the field value but reuse the method from parent.

//protected String getName(){return name;} //commented out

}

}

public class Test {

public static void main(String[] args) {

ParentForm pF = new ParentForm();

ChildForm cF = new ChildForm();

System.out.println(cF.getName() + " vs " + cF.getClass().getName());

}

}

Yields output:

ParentForm vs ChildForm

Can you please explain the output in similar terms ?

deepinjavaa at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 25
Actually, never mind. x.getClass().getName() is a built-in method.duh.
deepinjavaa at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 26

>

> Thanks for the reply. And I understand there are

> different ways to get this done. I just wanted to

> understand the concept or reasoning behind this

> behaviour which is only with fields - not methods.

>

> When we redeclare a variable in the child, it

> "shadows" it. But when we redeclare a method in the

> child, it overrides it. I understand the fact and the

> design. What I don't understand is why they have

> chosen to treat child variables differently from

> child methods ?

Because ideally an "object" should only expose behavior.

If polymorphic data was allowed it would, by definition, break that.

jschella at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 27
> Actually, never mind. x.getClass().getName() is a> built-in method.duh.Huh? What do you mean a "built-in" method? Methods are methods. They follow the same rules regardless of whether they're in the core API or you wrote them.
jverda at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...
# 28
> > Because ideally an "object" should only expose> behavior. > > If polymorphic data was allowed it would, by> definition, break that.Would break that definition-agreed.
deepinjavaa at 2007-7-21 22:23:11 > top of Java-index,Java Essentials,Java Programming...