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

Why not just use getClass().getName()?
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 >

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

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]
> 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?
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.
}
}
> > 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.
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");
}
}
> > > 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 >

> 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");
}
> And add this into ParentForm?> public ParentForm() {>this("ParentForm");> }Indeed, thanks... :)
And editpublic ParentForm(String name) {...to make it protected? I'll stop now :-)
> 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 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 >

> 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... :-)
> > > > 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 >

> 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 ?
> 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.
> 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 !
> 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.
> Can you please explain the above output in the same> way ? thanks.Not without knowing which version of those classes you're using. :)
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 ?
Actually, never mind. x.getClass().getName() is a built-in method.duh.
>
> 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.
> 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 >

> > Because ideally an "object" should only expose> behavior. > > If polymorphic data was allowed it would, by> definition, break that.Would break that definition-agreed.