Variable Inheritance in Java - java

I have a Super class and a bunch of subclasses. I want to have one field that has the same name in every single subclass, but I do not want it to be defined in the super class, or at least I do not want to use that 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 run Little, this is the output
Big was here: told you, BIG
I am not sure why 'told you' is printed out while tellMe refers to "BIG". How can both be true?
My problem is that I want the method tellMe() to be in Big, and to have the variable tellMe (that it will actually return) to be defined in all the subclasses. The only way I can get this to work is as I have written, by rewriting the tellMe() method in each subclass. But doesn't that defeat the whole purpose of inheritance??? Please help
EDIT: I do not use the constructor in my subclasses. All I want is a field that can be set in all subclasses and a method in the super that uses those values. I don't understand why this isn't possible because every subclass would have to implement it, so it would make sense... If this simply is not possible, let me know please

Fields are not virtual, unlike methods. For this reason, it is a bad idea to declare fields with the same name as a field in another class in the hierarchy. The field referred to in theMethod is always going to be from Big (i.e. when you declare a field with the same name, it just hides the old field when in the scope of the replacing class, but doesn't replace it).
One solution would be to override a 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's field).

You can overwrite the value of Big.tellMe in the constructor of Little.
get rid of:
public String tellMe = "little";
and change the Little constructor to:
public Little(){
tellMe = "little";
}
at that point, you can get rid of Little.tellMe() also.

What you are doing is hiding the super class field, not overriding it, as the Java documentation states.
And it's also stated that it's not a good idea to do it.
So, the dynamic lookup won't work as for a method. If the variable is read from the son class, it will take "its" field value.
On the top class, the other one.
What you can override in Java is the behaviour, so what I would suggest is to
define a method
public String tellMe() {
return "Whatever";
}
that you can override in the subclasses to return whatever string you need.

Instead of defining tellMe inside of Big (since you said you do not want to define/use that value in Big) you can create a function in Big:
public abstract String tellMeString();
And define that in each subclass like so (for Little):
public String tellMeString()
{
return "Little";
}
Then theMethod can execute:
System.out.println ("Big was here: " + tellMe() + ", " + tellMeString());
In this case you wouldn't have to define a variable "tellMe" at all, you just override tellMeString in each subclass to return different Strings.

Fields are not inherited as you are expected. You can access the super class' field (unless it is private) from subclass. But you cannot "override" field. This is why tellMe used by method implemented in super class Big uses variable defined in the same class.
If you want inheritance use methods. For example you can implement method "tellMe()" that returns "BIG" in super class and "little" in subclass:
class Big {
protected String tellMe() {
return "BIG";
}
}
class Little {
#Override
protected String tellMe() {
return "Little";
}
}
Alternatively you can initialize variable tellMe in 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 "Little": the variable in super class was initialized when constructing the object; the method defined in super class returned this variable.

Methods can be overridden, fields are visible at the scope where they're 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 is:
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 the Big version of field. doIt2() is defined in Big, but overridden in Small. The Big.doIt2() sees the Big version of field, the Small.doIt2() version sees the Small version of field.
As others have pointed out, it's a pretty bad idea to do this - a better approach is to set the new value in the subclass constructor, or to use a method which is overridden.

Related

Difference between assignment to object variable and class variable/attribute [duplicate]

I know that this refers to a current object. But I do not know when I really need to use it. For example, will be there any difference if I use x instead of this.x in some of the methods? May be x will refer to a variable which is local for the considered method? I mean variable which is seen only in this method.
What about this.method()? Can I use it? Should I use it. If I just use method(), will it not be, by default, applied to the current object?
The this keyword is primarily used in three situations. The first and most common is in setter methods to disambiguate variable references. The second is when there is a need to pass the current class instance as an argument to a method of another object. The third is as a way to call alternate constructors from within a constructor.
Case 1: Using this to disambiguate variable references. In Java setter methods, we commonly pass in an argument with the same name as the private member variable we are attempting to set. We then assign the argument x to this.x. This makes it clear that you are assigning the value of the parameter "name" to the instance variable "name".
public class Foo
{
private String name;
public void setName(String name) {
this.name = name;
}
}
Case 2: Using this as an argument passed to another object.
public class Foo
{
public String useBarMethod() {
Bar theBar = new Bar();
return theBar.barMethod(this);
}
public String getName() {
return "Foo";
}
}
public class Bar
{
public void barMethod(Foo obj) {
obj.getName();
}
}
Case 3: Using this to call alternate constructors. In the comments, trinithis correctly pointed out another common use of this. When you have multiple constructors for a single class, you can use this(arg0, arg1, ...) to call another constructor of your choosing, provided you do so in the first line of your constructor.
class Foo
{
public Foo() {
this("Some default value for bar");
//optional other lines
}
public Foo(String bar) {
// Do something with bar
}
}
I have also seen this used to emphasize the fact that an instance variable is being referenced (sans the need for disambiguation), but that is a rare case in my opinion.
The second important use of this (beside hiding with a local variable as many answers already say) is when accessing an outer instance from a nested non-static class:
public class Outer {
protected int a;
public class Inner {
protected int a;
public int foo(){
return Outer.this.a;
}
public Outer getOuter(){
return Outer.this;
}
}
}
You only need to use this - and most people only use it - when there's an overlapping local variable with the same name. (Setter methods, for example.)
Of course, another good reason to use this is that it causes intellisense to pop up in IDEs :)
The only need to use the this. qualifier is when another variable within the current scope shares the same name and you want to refer to the instance member (like William describes). Apart from that, there's no difference in behavior between x and this.x.
"this" is also useful when calling one constructor from another:
public class MyClass {
public MyClass(String foo) {
this(foo, null);
}
public MyClass(String foo, String bar) {
...
}
}
There are a lot of good answers, but there is another very minor reason to put this everywhere. If you have tried opening your source codes from a normal text editor (e.g. notepad etc), using this will make it a whole lot clearer to read.
Imagine this:
public class Hello {
private String foo;
// Some 10k lines of codes
private String getStringFromSomewhere() {
// ....
}
// More codes
public class World {
private String bar;
// Another 10k lines of codes
public void doSomething() {
// More codes
foo = "FOO";
// More codes
String s = getStringFromSomewhere();
// More codes
bar = s;
}
}
}
This is very clear to read with any modern IDE, but this will be a total nightmare to read with a regular text editor.
You will struggle to find out where foo resides, until you use the editor's "find" function. Then you will scream at getStringFromSomewhere() for the same reason. Lastly, after you have forgotten what s is, that bar = s is going to give you the final blow.
Compare it to this:
public void doSomething() {
// More codes
Hello.this.foo = "FOO";
// More codes
String s = Hello.this.getStringFromSomewhere();
// More codes
this.bar = s;
}
You know foo is a variable declared in outer class Hello.
You know getStringFromSomewhere() is a method declared in outer class as well.
You know that bar belongs to World class, and s is a local variable declared in that method.
Of course, whenever you design something, you create rules. So while designing your API or project, if your rules include "if someone opens all these source codes with a notepad, he or she should shoot him/herself in the head," then you are totally fine not to do this.
this is useful in the builder pattern.
public class User {
private String firstName;
private String surname;
public User(Builder builder){
firstName = builder.firstName;
surname = builder.surname;
}
public String getFirstName(){
return firstName;
}
public String getSurname(){
return surname;
}
public static class Builder {
private String firstName;
private String surname;
public Builder setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder setSurname(String surname) {
this.surname = surname;
return this;
}
public User build(){
return new User(this);
}
}
public static void main(String[] args) {
User.Builder builder = new User.Builder();
User user = builder.setFirstName("John").setSurname("Doe").build();
}
}
Unless you have overlapping variable names, its really just for clarity when you're reading the code.
#William Brendel answer provided three different use cases in nice way.
Use case 1:
Offical java documentation page on this provides same use-cases.
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.
It covers two examples :
Using this with a Field and Using this with a Constructor
Use case 2:
Other use case which has not been quoted in this post: this can be used to synchronize the current object in a multi-threaded application to guard critical section of data & methods.
synchronized(this){
// Do some thing.
}
Use case 3:
Implementation of Builder pattern depends on use of this to return the modified object.
Refer to this post
Keeping builder in separate class (fluent interface)
Google turned up a page on the Sun site that discusses this a bit.
You're right about the variable; this can indeed be used to differentiate a method variable from a class field.
private int x;
public void setX(int x) {
this.x=x;
}
However, I really hate that convention. Giving two different variables literally identical names is a recipe for bugs. I much prefer something along the lines of:
private int x;
public void setX(int newX) {
x=newX;
}
Same results, but with no chance of a bug where you accidentally refer to x when you really meant to be referring to x instead.
As to using it with a method, you're right about the effects; you'll get the same results with or without it. Can you use it? Sure. Should you use it? Up to you, but given that I personally think it's pointless verbosity that doesn't add any clarity (unless the code is crammed full of static import statements), I'm not inclined to use it myself.
Following are the ways to use ‘this’ keyword in java :
Using this keyword to refer current class instance variables
Using this() to invoke current class constructor
Using this keyword to return the current class instance
Using this keyword as method parameter
https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
when there are two variables one instance variable and other local variable of the same name then we use this. to refer current executing object to avoid the conflict between the names.
this is a reference to the current object. It is used in the constructor to distinguish between the local and the current class variable which have the same name. e.g.:
public class circle {
int x;
circle(int x){
this.x =x;
//class variable =local variable
}
}
this can also be use to call one constructor from another constructor. e.g.:
public class circle {
int x;
circle() {
this(1);
}
circle(int x) {
this.x = x;
}
}
Will be there any difference if I use "x" instead of "this.x" in some of the methods?
Usually not. But it makes a difference sometimes:
class A {
private int i;
public A(int i) {
this.i = i; // this.i can be used to disambiguate the i being referred to
}
}
If I just use "method()", will it not be, by default, applied to the current object?
Yes. But if needed, this.method() clarifies that the call is made by this object.
this does not affect resulting code - it is compilation time operator and the code generated with or without it will be the same. When you have to use it, depends on context. For example you have to use it, as you said, when you have local variable that shadows class variable and you want refer to class variable and not local one.
edit: by "resulting code will be the same" I mean of course, when some variable in local scope doesn't hide the one belonging to class. Thus
class POJO {
protected int i;
public void modify() {
i = 9;
}
public void thisModify() {
this.i = 9;
}
}
resulting code of both methods will be the same. The difference will be if some method declares local variable with the same name
public void m() {
int i;
i = 9; // i refers to variable in method's scope
this.i = 9; // i refers to class variable
}
With respect to William Brendel's posts and dbconfessions question, regarding case 2. Here is an example:
public class Window {
private Window parent;
public Window (Window parent) {
this.parent = parent;
}
public void addSubWindow() {
Window child = new Window(this);
list.add(child);
}
public void printInfo() {
if (parent == null) {
System.out.println("root");
} else {
System.out.println("child");
}
}
}
I've seen this used, when building parent-child relation's with objects. However, please note that it is simplified for the sake of brevity.
To make sure that the current object's members are used. Cases where thread safety is a concern, some applications may change the wrong objects member values, for that reason this should be applied to the member so that the correct object member value is used.
If your object is not concerned with thread safety then there is no reason to specify which object member's value is used.

Is there a more specific reason to use "this" in Java other than style and readability? [duplicate]

I know that this refers to a current object. But I do not know when I really need to use it. For example, will be there any difference if I use x instead of this.x in some of the methods? May be x will refer to a variable which is local for the considered method? I mean variable which is seen only in this method.
What about this.method()? Can I use it? Should I use it. If I just use method(), will it not be, by default, applied to the current object?
The this keyword is primarily used in three situations. The first and most common is in setter methods to disambiguate variable references. The second is when there is a need to pass the current class instance as an argument to a method of another object. The third is as a way to call alternate constructors from within a constructor.
Case 1: Using this to disambiguate variable references. In Java setter methods, we commonly pass in an argument with the same name as the private member variable we are attempting to set. We then assign the argument x to this.x. This makes it clear that you are assigning the value of the parameter "name" to the instance variable "name".
public class Foo
{
private String name;
public void setName(String name) {
this.name = name;
}
}
Case 2: Using this as an argument passed to another object.
public class Foo
{
public String useBarMethod() {
Bar theBar = new Bar();
return theBar.barMethod(this);
}
public String getName() {
return "Foo";
}
}
public class Bar
{
public void barMethod(Foo obj) {
obj.getName();
}
}
Case 3: Using this to call alternate constructors. In the comments, trinithis correctly pointed out another common use of this. When you have multiple constructors for a single class, you can use this(arg0, arg1, ...) to call another constructor of your choosing, provided you do so in the first line of your constructor.
class Foo
{
public Foo() {
this("Some default value for bar");
//optional other lines
}
public Foo(String bar) {
// Do something with bar
}
}
I have also seen this used to emphasize the fact that an instance variable is being referenced (sans the need for disambiguation), but that is a rare case in my opinion.
The second important use of this (beside hiding with a local variable as many answers already say) is when accessing an outer instance from a nested non-static class:
public class Outer {
protected int a;
public class Inner {
protected int a;
public int foo(){
return Outer.this.a;
}
public Outer getOuter(){
return Outer.this;
}
}
}
You only need to use this - and most people only use it - when there's an overlapping local variable with the same name. (Setter methods, for example.)
Of course, another good reason to use this is that it causes intellisense to pop up in IDEs :)
The only need to use the this. qualifier is when another variable within the current scope shares the same name and you want to refer to the instance member (like William describes). Apart from that, there's no difference in behavior between x and this.x.
"this" is also useful when calling one constructor from another:
public class MyClass {
public MyClass(String foo) {
this(foo, null);
}
public MyClass(String foo, String bar) {
...
}
}
There are a lot of good answers, but there is another very minor reason to put this everywhere. If you have tried opening your source codes from a normal text editor (e.g. notepad etc), using this will make it a whole lot clearer to read.
Imagine this:
public class Hello {
private String foo;
// Some 10k lines of codes
private String getStringFromSomewhere() {
// ....
}
// More codes
public class World {
private String bar;
// Another 10k lines of codes
public void doSomething() {
// More codes
foo = "FOO";
// More codes
String s = getStringFromSomewhere();
// More codes
bar = s;
}
}
}
This is very clear to read with any modern IDE, but this will be a total nightmare to read with a regular text editor.
You will struggle to find out where foo resides, until you use the editor's "find" function. Then you will scream at getStringFromSomewhere() for the same reason. Lastly, after you have forgotten what s is, that bar = s is going to give you the final blow.
Compare it to this:
public void doSomething() {
// More codes
Hello.this.foo = "FOO";
// More codes
String s = Hello.this.getStringFromSomewhere();
// More codes
this.bar = s;
}
You know foo is a variable declared in outer class Hello.
You know getStringFromSomewhere() is a method declared in outer class as well.
You know that bar belongs to World class, and s is a local variable declared in that method.
Of course, whenever you design something, you create rules. So while designing your API or project, if your rules include "if someone opens all these source codes with a notepad, he or she should shoot him/herself in the head," then you are totally fine not to do this.
this is useful in the builder pattern.
public class User {
private String firstName;
private String surname;
public User(Builder builder){
firstName = builder.firstName;
surname = builder.surname;
}
public String getFirstName(){
return firstName;
}
public String getSurname(){
return surname;
}
public static class Builder {
private String firstName;
private String surname;
public Builder setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder setSurname(String surname) {
this.surname = surname;
return this;
}
public User build(){
return new User(this);
}
}
public static void main(String[] args) {
User.Builder builder = new User.Builder();
User user = builder.setFirstName("John").setSurname("Doe").build();
}
}
Unless you have overlapping variable names, its really just for clarity when you're reading the code.
#William Brendel answer provided three different use cases in nice way.
Use case 1:
Offical java documentation page on this provides same use-cases.
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.
It covers two examples :
Using this with a Field and Using this with a Constructor
Use case 2:
Other use case which has not been quoted in this post: this can be used to synchronize the current object in a multi-threaded application to guard critical section of data & methods.
synchronized(this){
// Do some thing.
}
Use case 3:
Implementation of Builder pattern depends on use of this to return the modified object.
Refer to this post
Keeping builder in separate class (fluent interface)
Google turned up a page on the Sun site that discusses this a bit.
You're right about the variable; this can indeed be used to differentiate a method variable from a class field.
private int x;
public void setX(int x) {
this.x=x;
}
However, I really hate that convention. Giving two different variables literally identical names is a recipe for bugs. I much prefer something along the lines of:
private int x;
public void setX(int newX) {
x=newX;
}
Same results, but with no chance of a bug where you accidentally refer to x when you really meant to be referring to x instead.
As to using it with a method, you're right about the effects; you'll get the same results with or without it. Can you use it? Sure. Should you use it? Up to you, but given that I personally think it's pointless verbosity that doesn't add any clarity (unless the code is crammed full of static import statements), I'm not inclined to use it myself.
Following are the ways to use ‘this’ keyword in java :
Using this keyword to refer current class instance variables
Using this() to invoke current class constructor
Using this keyword to return the current class instance
Using this keyword as method parameter
https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
when there are two variables one instance variable and other local variable of the same name then we use this. to refer current executing object to avoid the conflict between the names.
this is a reference to the current object. It is used in the constructor to distinguish between the local and the current class variable which have the same name. e.g.:
public class circle {
int x;
circle(int x){
this.x =x;
//class variable =local variable
}
}
this can also be use to call one constructor from another constructor. e.g.:
public class circle {
int x;
circle() {
this(1);
}
circle(int x) {
this.x = x;
}
}
Will be there any difference if I use "x" instead of "this.x" in some of the methods?
Usually not. But it makes a difference sometimes:
class A {
private int i;
public A(int i) {
this.i = i; // this.i can be used to disambiguate the i being referred to
}
}
If I just use "method()", will it not be, by default, applied to the current object?
Yes. But if needed, this.method() clarifies that the call is made by this object.
this does not affect resulting code - it is compilation time operator and the code generated with or without it will be the same. When you have to use it, depends on context. For example you have to use it, as you said, when you have local variable that shadows class variable and you want refer to class variable and not local one.
edit: by "resulting code will be the same" I mean of course, when some variable in local scope doesn't hide the one belonging to class. Thus
class POJO {
protected int i;
public void modify() {
i = 9;
}
public void thisModify() {
this.i = 9;
}
}
resulting code of both methods will be the same. The difference will be if some method declares local variable with the same name
public void m() {
int i;
i = 9; // i refers to variable in method's scope
this.i = 9; // i refers to class variable
}
With respect to William Brendel's posts and dbconfessions question, regarding case 2. Here is an example:
public class Window {
private Window parent;
public Window (Window parent) {
this.parent = parent;
}
public void addSubWindow() {
Window child = new Window(this);
list.add(child);
}
public void printInfo() {
if (parent == null) {
System.out.println("root");
} else {
System.out.println("child");
}
}
}
I've seen this used, when building parent-child relation's with objects. However, please note that it is simplified for the sake of brevity.
To make sure that the current object's members are used. Cases where thread safety is a concern, some applications may change the wrong objects member values, for that reason this should be applied to the member so that the correct object member value is used.
If your object is not concerned with thread safety then there is no reason to specify which object member's value is used.

Java Inheritance: Overwritten or hidden methods

When a class extends another, it inherits all methods and variables of the superclass. Both methods and variables can be used differently in the subclass, if you define it differently in the subclass with the same signature.
Now Oracle distincts between overwriting and hiding (http://docs.oracle.com/javase/tutorial/java/IandI/override.html).
It says that an instance method overwrites its superclass's method, while a class method hides it.
"The distinction between hiding and overriding has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass."
Lets assume I have 2 classes Yes and Maybe. Yes extends Maybe.
Maybe has String a.
class Maybe {
String a;
public static void printOut() {
System.out.println("Maybe");
}
public void printAndSet() {
a = "Maybe";
System.out.println(a);
}
}
class Yes extends Maybe {
public static void printOut() {
System.out.println("Yes");
}
pubilc void printAndSet() {
a = "Yes";
}
}
class Print{
public static void mail(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
Maybe.printOut();
Yes.printOut();
m.printAndSet();
y.printAndSet();
}
And I say: It will print out
maybe
yes
maybe
yes
But after I read the Oracle article I thought it would have to print out:
yes
yes
maybe
yes
Because the instance method overwrites its superclass method.
I'm quite sure I am right with the output, but I'm sure aswell, that Oracle knows
better so I'm thinking I just didn't understand the article.
It can't be true that when I call an instance method from an object of a superclass, that it uses the overwritten method.
So I do not understand why to distinguish overwriting and hiding!
Can someone help out?
Edit; Inserted code instead of describing the classes!
Static methods can't be overridden at all. They're not called polymorphically, since they don't act on an instance of the class, but on the class itself.
If you call Maybe.printOut(), it will call the static printOut() method defined in Maybe. The fact that there is also a method printOut() defined in Yes is irrelevant: those two methods have nothing in common, except their name.
Note that you could confirm or infirm your doubts by simply writing a program and executing it.
The problem with hiding methods only occurs when you start calling static methods on an instance of an object. This is very bad practice, and should never be done. If you don't respect this rule, and have the following:
Maybe m = new Maybe();
Maybe y = new Yes();
m.printOut(); // DON'T DO THAT: it should be Maybe.printOut();
y.printOut(); // DON'T DO THAT: it should be Maybe.printOut() or Yes.printOut();
the result will be maybe maybe, because in the case of static methods, what counts is not the concrete type of the objects (Maybe and Yes), but their declared type (Maybe and Maybe).
public class Parent {
public String test(){
return "p";
}
public static String testStatic(){
return "sp";
}
}
public class Child extends Parent {
public String test(){
return "c";
}
public static String testStatic(){
return "sc";
}
}
public class Demo{
public static void main(String[] args) {
Parent p =new Parent();
Child c = new Child();
Parent pc = new Child();
System.out.println(p.test());
System.out.println(c.test());
System.out.println(pc.test());
//Although this is not the correct way of calling static methods
System.out.println(p.testStatic());
System.out.println(c.testStatic());
System.out.println(pc.testStatic());
}
}
OUTPUT will be: - (static method vs instance method)
p
c
c
sp
sc
sp
Take the following example, based on your example:
public class SO11720216 {
static class Maybe {
public static void hidden() { System.out.println("static maybe"); }
public void overwritten() { System.out.println("instance maybe"); }
public void inherited() { hidden(); }
public void called() { overwritten(); inherited(); }
}
static class Yes extends Maybe {
public static void hidden() { System.out.println("static yes"); }
public void overwritten() { System.out.println("instance yes"); }
}
public static void main(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
m.called(); /* prints:
instance maybe
static maybe
*/
y.called(); /* prints:
instance yes
static maybe
*/
Yes.hidden(); /* prints: static yes */
y.hidden(); /* bad style! prints: static yes */
}
}
The call to overwritten will be overwritten by each derived class. So every method will use the implementation belonging to the current object. On the other hand, the call to hidden will always use the implementation of the defining class. Hence Maybe.called will always call Maybe.hidden, and never Yes.hidden. To call Yes.hidden, you'll have to do so from within a method in Yes, or using a qualified name.
To phrase this differently:
To overwrite a method means that whenever the method is called on an object of the derived class, the new implementation will be called.
To hide a method means that an unqualified call to that name (like the hidden() call in the inherited() method of my above example) in the scope of this class (i.e. in the body of any of its methods, or when qualified with the name of this class) will now call a completely different function, requiring a qualification to access the static method of the same name from the parent class.
Perhaps your confusion comes from the fact that you assumed overwriting to affect all calls to the method, even for objects of the base class.

Java passing subclass instance data to superclass constructors

Does anybody know if there's a way in Java to set the value of an instance variable in a subclass before calling the superclass constructor. I have a brief schematic below of what I'm trying to accomplish -- I need to set up the instance variables defined in the superclass differently depending on the subclass type, but I still want to be able to share common non-constructor code among different instances of the subclass.
Is there any clean way to do this, maybe some sort of coding pattern that I'm missing or something? Thanks in advance for any ideas.
public abstract class ConstraintSatisfactionProblem {
final Set<Variable> variables;
final Set<Constraint> constraints;
public Foo() {
this.variables = setupVariables();
this.constraints = setupConstraints();
}
public abstract Set<Variable> setupVariables();
public abstract Set<Constraint> setupConstraints();
public Map<Variable, Constraint> solve() { ... }
}
public class WordSquare extends ConstraintSatisfactionProblem {
final int size;
final static Set<Character> domain = ...;
public WordSquare() {
super(); // can I simulate calling super() after setting this.value = 4?
this.value = 4;
}
public Set<Variable> setupVariables() {
this.variables = new HashSet<Variable>();
for(int row = 0; row < size; ++row) {
for(int col = 0; col < size; ++col) {
variables.add(new Variable<Pair, Character>(new Pair(row, col), domain);
}
}
return this.variables;
}
public Set<Constraint> setupConstraints() {
// setup code specific to this problem
}
}
public class Cryptarithmetic extends ConstraintSatisfactionProblem {
final String problem;
public Cryptarithmetic(String problem) {
super();
this.problem = problem;
}
public Set<Variable> setupVariables() {
this.variables = new HashSet<Variable>();
for(char c : problem.toCharArray()) {
variables.add(new Variable<Character, Integer>(c, getDomain());
}
}
return this.variables;
}
public Set<Constraint> setupConstraints() {
// setup code specific to this problem
}
}
Firstly, please don't.
Secondly, really it's a really bad idea. Don't. Think about what you are trying to do in a broader context.
If you absolutely must do, you can stash it in a ThreadLocal. You can call a (non-instance) method by evaluating an expression the result of which is passed to a super() or this() (possibly the only reason why you need a second, private constructor that possibly takes a Void (capital 'V') argument). It's so evil, I am not going to even write the code down.
In your edited example code, just pass the sets into a protected constructor. If you have many arguments possibly some subclasses being special about some arguments, you might want to wrap all the arguments into a single argument object.
There is another really hacky approach, so long as you have -target 1.4 or later (which you should do!). Make the subclass an inner class (possibly anonymous). The references to the outer this and other captured variables are available before calling the super constructor.
public class Outer {
// What a hack!
private static abstract class Base {
Base() {
hello(); // Calling a virtual method in a constructor - poor form.
}
abstract void hello();
}
public static void main(String[] args) {
// Do not do this.
final String hi = "Hi!";
new Base() {
void hello() {
// Really, don't do it.
System.err.println(hi);
}
};
}
}
Place the common code you want to run in a protected method instead of in the constructor. Call that method when you wish.
You should never call any "alien" method (ie. overridable method of this class, or any method from any other class) form within a constructor. As long as the object is not fully initialized, you may have side-effects like the one you see.
In your case, in the subclass constructor, super() is called even before the "value" is set to 4. This means, the superclass constructor is called, then calls the "setup" method, while the "value" is still at 0.
Only once the superclass constructor returns, the "value" is set to 4. And it's too late then.
What I would recommend, is to set the "o1" variable to protected, so that subclasses can set its value themselves.
In Java, if you want to call a base class's constructor, you have to do it on the first line of your sub-class's constructor. So the answer is no, you can't set this.value before calling the super class's constructor.
But your sub-class's setup() method is already called in the super's constructor. Why don't you set your value there?
UPDATE:
Sorry, I didn't pay attention that your 'setup()' method returns a value. What you could do is make an abstract init() method in your super class, and call it in your super constructor before you call the setup() method. This way sub-classes will be forced to implement init(), and you would know that that is the place to initialize any sub-class's members before they are used in your super-class.
That being said, this approach does not force safety on you. When you call the super constructor from your sub-constructor, the sub-class instance is just starting to get created. It still needs to run the rest of the code in the sub-constructor before the object is safely created.
And in this situation, the super-constructor goes and calls the init() method on your just-in-the-process-of-creation sub-class. This means that if you go with approach, you have to be extra careful about what you do in the init() class.
Like others have said, don't do this. If you want to share some code between these classes, try containment/encapsulation instead of inheritance.
public class Foo {
private final Object o1;
public Foo(Object o) {
o1 = o;
}
public void complexMethodCommonToAllSubclassesOfFoo() { ... }
}
public class Bar {
private final int value;
private final Foo foo;
public Bar() {
super();
this.value = 4;
this.foo = new Foo( new Object() ); // or whatever
}
// If you need to expose complexMethodCommonToAllSubclassesOfFoo to clients of this class, just add the method and delegate to foo like this
public void complexMethodCommonToAllSubclassesOfFoo() {
foo.complexMethodCommonToAllSubclassesOfFoo();
}
}
I need to set up the instance variables defined in the superclass differently depending on the subclass type, but I still want to be able to share common non-constructor code among different instances of the subclass.
In that case, create a protected constructor in the superclass, and pass all of the customized values to it when you construct the subclass.

How to write proper OOP code in order to avoid having field initialization issues?

Running this piece of code will print null
public class Weird {
static class Collaborator {
private final String someText;
public Collaborator(String text) {
this.someText = text;
}
public String asText() {
return this.someText;
}
}
static class SuperClass {
Collaborator collaborator;
public SuperClass() {
initializeCollaborator();
}
protected void initializeCollaborator() {
this.collaborator = new Collaborator("whatever");
}
public String asText() {
return this.collaborator.asText();
}
}
static class SubClass extends SuperClass {
String someText = "something";
#Override
protected void initializeCollaborator() {
this.collaborator = new Collaborator(this.someText);
}
}
public static void main(String[] arguments) {
System.out.println(new Weird.SubClass().asText());
}
}
(Here is also the GitHub Gist)
Now, I know why this happens (it's because the field of the superclass is initialized and then the constructor of the superclass is called, before the field of the subclass is initialized)
The questions are:
What is the design issue here? What is wrong with this design, from an OOP point of view, so that the result looks weird to a programmer? What OOP principles are being broken through this design?
How to refactor so it does not work 'weird' and is proper OOP code?
What's wrong with the design: you're calling an instance method from a constructor, and then overriding it in a subclass. Don't do that. Ideally, only call private or final instance methods, or static methods, from constructor bodies. You're also exposing a field (which is an implementation detail) outside SuperClass, which isn't a great idea - but writing a protected setCollaborator method and calling that from initializeCollaborator would give the same problem.
As to how to fix it - it's not really clear what you're trying to achieve. Why do you need the initializeCollaborator method at all? There can be various ways of approaching this problem, but they really depend on knowing eaxctly what you're trying to achieve. (Heck, in some cases the best solution is not to use inheritance in the first place. Prefer composition over inheritance, and all that :)
My issue with the design is the someText string should either be an explicit dependency (or "collaborator") of the Collaborator object, or of SubClass, or explicitly a part of the global context (so a constant or a property of a shared context object).
Ideally, either Collaborator should be responsible for retrieving its dependencies; or, if SubClass is responsible for this, it should have someText as a dependency (even if it's always initialised to the same value), and only initialise Collaborator when someText is set.
Conceptually speaking, the dependency relation between objects in the design imposes a partial ordering of the initialisation. The mechanism to implement this ordering should always be explicit in your design, instead of relying on implementation details of the Java language.
An (overengineered) example:
interface ICollaboratorTextLocator {
String getCollaboratorText();
}
class ConstantCollaboratorTextLocator implements ICollaboratorTextLocator {
String text;
ConstantCollaboratorTextLocator(String text) {
this.text = text;
}
}
class SuperClass {
Collaborator collaborator;
public setCollaboratorTextLocator(ICollaboratorTextLocator locator) {
collaborator = new Collaborator(locator.getCollaboratorText());
}
SuperClass() {
setCollaboratorTextLocator(new ConstantCollaboratorTextLocator("whatever"));
}
}
class SubClass {
String text = "something";
SubClass() {
setCollaboratorTextLocator(new ConstantCollaboratorTextLocator(text));
}
}
(Now excuse me, I need to go stand under a waterfall after writing something called ConstantCollaboratorTextLocator.)
Instead of using the intializeCollaborator method, make the Collaborator a parameter on the constructor and call it using super(new Collaborator(..)) from the child.

Categories