Problem: What I want to achieve is to have an instance of a Parent
class propagate changes of its local variables to Child
class instances derived directly from the Parent
. My current approach is to extend
the Parent
class to the Child
s but it doesn't provide any way to access the Parent
instance variables.
Example: Let's say that the parent class stores a String
which contains a name. I want 1 child to stem from a parent whose String
name is "George" and 1 other child to stem from a parent whose String
name is "Nick". When the String
stored in the "George" parent class changes from "George" to "Patrick" I want it to be changed for his child but not for the child of "Nick".
Can this be done without too much computational overhead?
Code Reference:
public class Parent {
private String name;
public Parent(String name) {
this.name = name;
}
public void changeName(String newName) {
name = newName;
}
public String getName() {
return name;
}
}
public class Child extends Parent {
private String parentName;
/**
* Currently derives the String directly which won't react to
* changes to the Parent class.
*/
public Child(Parent p) {
this.parentName = p.getName();
}
public getParentName() {
return parentName;
}
}
public class mainApp {
public static void main(String[] cmdArgs) {
Parent George = new Parent("George");
Parent Nick = new Parent("Nick");
Child a = new Child(George);
Child b = new Child(Nick);
George.changeName("Patrick");
// Prints "George", should print "Patrick"
System.out.println(a.getParentName());
// Prints "Nick", should print "Nick"
System.out.println(b.getParentName());
}
}
Solution: It is actually possible to achieve the above by using Object Composition.
By keeping a reference to the original Parent
that was used when creating the Child
class instance, all changes conducted on the Parent
instance will be reflected on the Child
instance.
In this way, a Child
can also be in an orphaned state where no Parent
instance was used to create it.
Solution Code:
public class Parent {
private String name;
public Parent(String name) {
this.name = name;
}
public void changeName(String newName) {
name = newName;
}
public String getName() {
return name;
}
}
// Extension is not required
public class Child {
private Parent parentReference;
public Child(Parent parentReference) {
this.parentReference = parentReference;
}
public getParentName() {
// We need to manually handle the case of a non-existent parent
if (parentReference == null) {
return "None";
} else {
return parentReference.getName();
}
}
}
public class mainApp {
public static void main(String[] cmdArgs) {
Parent George = new Parent("George");
Parent Nick = new Parent("Nick");
Child a = new Child(George);
Child b = new Child(Nick);
Child c = new Child(null);
George.changeName("Patrick");
// Prints "Patrick", should print "Patrick"
System.out.println(a.getParentName());
// Prints "Nick", should print "Nick"
System.out.println(b.getParentName());
// Prints "None", should print "None"
System.out.println(c.getParentName());
}
}
You're taking the terms "Parent" and "Child" in a very literal sense in your example but that is not always applicable.
You can only use inheritance when there is a fixed relationship between a type and a subtype. Like, "a Bicycle is a Vehicle" or a "Giraffe is an Animal". Those relations are the same for every instance of Bicycle and Giraffe. But what you're describing is not like this.
For your case, you can use composition to model.
Person
has a name
.Person
has a parent
(which may be left null
to indicate "don't know" or "don't care")Person
has zero or more children
class Person {
String name;
Person parent;
Person(String name, Person parent) {
this.name = name;
this.parent = parent;
}
// etc (getters, setters)
}
public class MainApp {
public static void main(String[] cmdArgs) {
Person george = new Person("George", null);
Person nick = new Person("Nick", null);
Person a = new Person("a", george);
Person b = new Person("b", george);
Person c = new Person("c", nick);
// etc.
}
}