Java inheritance of variables

I have a Super class and a bunch of subclasses. I want to have one field with the same name in each subclass, but I do not want it to be defined in the superclass, or at least I do not want to use this value. This is what I have right now

public abstract class Big { public String tellMe = "BIG"; public Big() {} public void theMethod() { System.out.println ("Big was here: " + tellMe() + ", " + tellMe); } public String tellMe() { return tellMe; } } public class Little extends Big{ public String tellMe = "little"; public Little(){} public String tellMe() { return "told you"; } public static void main(String [] args) { Little l = new Little(); l.theMethod(); } } 

When I launch Little, this is the conclusion

Big was here: told you BIG

I'm not sure why "told you" is printed, and tellMe is "BIG". How can both be true?

My problem is that I want the tellMe () method to be in Big, and that the tellMe variable (which it really returned) is defined in all subclasses. The only way to get this to work, as I wrote, is rewriting the tellMe () method in each subclass. But doesn't that defeat the whole purpose of inheritance ??? Please, help

EDIT: I do not use constructor in my subclasses. All I want is a field that can be set in all subclasses and in the super method that uses these values. I donโ€™t understand why this is impossible, because each subclass would have to implement it, so it would make sense ... If this is simply impossible, please let us know.

+4
source share
6 answers

Fields are not virtual, unlike methods. For this reason, it is a bad idea to declare fields with the same name as the field in another class in the hierarchy. The field specified in theMethod will always be from Big (i.e., when you declare a field with the same name, it simply hides the old field when it is in the class replacement area, but does not replace it).

One solution would be to override the method that gets the field from the current class:

In theMethod replace the tellMe field with getTellMe() and for all classes, override getTellMe() to return the correct value (or the field that hides the superclass field).

+6
source

You can overwrite the Big.tellMe value in the Little constructor.

to get rid of:

 public String tellMe = "little"; 

and change the Little constructor to:

 public Little(){ tellMe = "little"; } 

at this point, you can also get rid of Little.tellMe() .

+2
source

What you are doing is hiding the superclass field and not overriding it, because it contains Java documentation . And he also stated that this is not a good idea.

Thus, dynamic search will not work the same as for the method. If the variable is read from the son class, it takes on the value of "its" field. In the upper class, another.

What you can override in Java is behavior, so I would suggest to define a method

 public String tellMe() { return "Whatever"; } 

which you can override in subclasses to return the necessary line.

+2
source

Instead of defining tellMe inside Big (since you said you did not want to define / use this value in Big), you can create a function in Big:

 public abstract String tellMeString(); 

And define that in each subclass, for example, (for Little):

 public String tellMeString() { return "Little"; } 

Then the method can do:

 System.out.println ("Big was here: " + tellMe() + ", " + tellMeString()); 

In this case, you would not need to define the tellMe variable at all, you simply override tellMeString in each subclass to return different lines.

+1
source

Fields are not inherited as you expected. You can access the superclass field (if it is not private) from a subclass. But you cannot override the field. This is why tellMe , used by the method implemented in the Big superclass, uses a variable defined in the same class.

If you want to use inheritance methods. For example, you can implement the โ€œtellMe ()โ€ method, which returns "BIG" in the superclass and "little" in the subclass:

 class Big { protected String tellMe() { return "BIG"; } } class Little { @Override protected String tellMe() { return "Little"; } } 

Alternatively, you can initialize the tellMe variable in the constructor:

 class Big { private String tellMe; public Big() { this("BIG"); } protected Big(String tellMe) { this.tellMe = tellMe; } protected String tellMe() { return "BIG"; } } class Little { public Little() { super("Little"); } } 

Now new Little().tellMe() will return โ€œSmallโ€: the variable in the superclass was initialized when building the object; The method defined in the superclass returned this variable.

+1
source

Methods can be overridden, fields are visible in the area where they are called.

 static class Big { String field = "BIG"; String bark() { return "(big bark)"; } void doIt() { System.out.format("field(%s) bark(%s)\n", field,bark()); } void doIt2() { System.out.format("2:field(%s) bark(%s)\n", field,bark()); } } static class Small extends Big { String field = "small"; String bark() { return "(small bark)"; } void doIt2() { System.out.format("2:field(%s) bark(%s)\n", field,bark()); } } public static void main(String... args) { Big b = new Big(); b.doIt(); b.doIt2(); Small s = new Small(); s.doIt(); s.doIt2(); } 

Output:

 field(BIG) bark((big bark)) 2:field(BIG) bark((big bark)) field(BIG) bark((small bark)) 2:field(small) bark((small bark)) 

since doIt () is defined in the Big class, it will always see a large version of the field. doIt2 () is defined in Big, but redefined in Small. Big.doIt2 () sees a large version of the field; the version of Small.doIt2 () sees a small version of the field.

As others have noted, this is a pretty bad idea - it's best to set a new value in the constructor of the subclass or use an overridden method.

+1
source

All Articles