I have a Parent.java class and 4 child classes as Child1.java, Child2.java and so on.
There are two methods
m1()
m2()
and one field
f1
Field f1 has different values based on the child class.
Method m1 has the common implementation so I have put it in Parent.java class. It also refers method m2.
Method m2 has common implemtation but it process field f1 which is different for all the child classes.
So my questions are as follows:
Q1. Should I place the field f1 in the parent class and let all the child classes inherit them and initialize them in their own constructors or Should I make a field f1 for all the child classes.
Q2. As the method m2 has common implementation but process field f1 which doesn't have same value for every child class, so should I place it in parent class or child class.
Q3. If I should place the method m2 in parent class, the there is one problem that method m1 (which have common implementation) refer method m2, so would it create any problem?
Place m2 and f1 in the parent class if m2's implementation is the same for all classes. If there's a specific part for each child class that can be run after the common part - separate it and place it in the child classes while calling super.m2(). Set f1 in each child class's constructor.
The result will look something like this:
public abstract class parent {
private int field = 0;
public parent(int f) {
field = f;
}
public void m1() { /* m1's implementation */ }
public void m2() { /* m2's common implementation */ }
}
public class child1 {
public child1() {
super(1);
}
#Override
public void m2() { super.m2() /* m2's child1 implementation */ }
}
public class child2 {
public child2() {
super(2);
}
#Override
public void m2() { super.m2() /* m2's child2 implementation */ }
}
This should allow you to push the maximum amount of code as far back in the hierarchy as it can go. Least code duplication.
Edited to fix trying to access a private member from a child class. Changed to setting it using the constructor.
In my opinion:
f1 should be in the parent class and initialized in the child constructor. This way, the get and set methods are only written once.
m2 should be in the parent class.
m1 should be also be in the parent class. Don't forget that you can also make methods abstract if they do not have a common implementation but exist in all child classes. This would allow you to call it from other methods in the parent class despite not being defined there. Also keep in mind that the parent class would also need to be abstract in this case.
From what you described, I don't see any problem with this implementation:
public class Parent {
private int f1;
public Parent(int f1) {
this.f1 = f1;
}
public void m1() { }
public void m2() {
// do something with f1
System.out.println(f1);
}
}
public class Child1 extends Parent {
private final int DEFAULT_FIELD_VALUE = 1;
public Child1() {
super(DEFAULT_FIELD_VALUE);
}
}
public class Child2 extends Parent {
public Child2(int value) {
super(value);
}
}
{...}
What you are trying to do sound like Template Method design pattern: http://en.wikipedia.org/wiki/Template_method_pattern
I suggest putting f1 in the parent class and declaring m2 abstract in the parent class (which will make the class abstract itself).
If the child classes differ only in the value of f1 then there is no point in even creating subclasses, you should just pass f1 in a constructor or use static factory methods to create instances for the different cases. For example:
public class Parent {
private Value f1;
private Parent(Value f1) {
this.f1 = f1;
}
public static Parent makeChild1() {
return new Parent(valueOfF1ForChild1);
}
public static Parent makeChild2() {
return new Parent(valueOfF1ForChild2);
}
}
Also, you might want to check out if an enumeration is suitable for your case.
Related
I am doing this:
Child child = (Child)parent;
Which gives me an error, I found it isn't possible to do it like this. I don't know exactly why, but I think it should be possible, if Child class inherits from Parent class, it contains the Parent object data.
My questions are:
Why it doesnt work?
How can i make this work, without setting every single parent's
attribute like this
:
class Parent{
public int parameter1;//...
public int parameter1000;
}
class Child extends Parent
{
public Child(Parent parent)
{
this.parameter1 = parent.parameter1;//...
this.parameter1000 = parent.parameter1000;
}
}
Well you could just do :
Parent p = new Child();
// do whatever
Child c = (Child)p;
Or if you have to start with a pure Parent object you could consider having a constructor in your parent class and calling :
class Child{
public Child(Parent p){
super(p);
}
}
class Parent{
public Parent(Args...){
//set params
}
}
Or the composition model :
class Child {
Parent p;
int param1;
int param2;
}
You can directly set the parent in that case.
You can also use Apache Commons BeanUtils to do this. Using its BeanUtils class you have access to a lot of utility methods for populating JavaBeans properties via reflection.
To copy all the common/inherited properties from a parent object to a child class object you can use its static copyProperties() method as:
BeanUtils.copyProperties(parentObj,childObject);
Note however that this is a heavy operation.
change 'this' to 'super' in your child constructor, and remove the parent parameter, instead replace that with the two parameters
int parameter1;//...int parameter1000; :)
class Parent{
public int parameter1;//...
public int parameter1000;
}
class Child extends Parent
{
public Child(int parameter1, int parameter1000)
{
super.parameter1 = parameter1
super.parameter1000 = parameter1000;
}
}
Do you really want to cast you parent into the child class? If the given Object (given as a Parent object) was created as a child class, you can access the correct functions without the cast. Here is an example:
In the main you see a Vector 'ps' to store Parent objects, but added are Child objects which extend from the Parent. While iterateing through that vector, I dont know which kind of child I get next (thus I cannot cast to the correct class), but due to the keyword Override of the function I call, the correct child/method is used.
import java.util.Vector;
import lib.Parent;
import lib.C1;
import lib.C2;
public class MyClass {
public static void main(String []args){
System.out.println("Hello World");
C1 c1 = new C1();
C2 c2 = new C2();
ps.add(c1);
ps.add(c2);
for(int k = 0; k < ps.size(); k++){
ps.get(k).setInteger(); // no cast needed
System.out.println("stored entity " + ps.get(k).i);
}
// or use a ranged for loop
for(Parent p: ps){
p.setInteger();
System.out.println("stored entity " + p.i);
}
}
static Vector<Parent> ps = new Vector<>();
}
The Parent class: The keyword abstract forces every child to implement that method, so if you have a Parent object you can safely call this method. Since the Parent class itself is abstract you wont have an object which is just a Parent object since that is not allowed and wont compile.
package lib;
public abstract class Parent{
public Integer i;
public abstract void setInteger();
}
And here are two Child classes which have an different implementation of the setInteger() method.
package lib;
import lib.Parent;
public class C1 extends Parent{
#Override
public void setInteger(){
i = new Integer(1);
}
}
Second Child:
package lib;
import lib.Parent;
public class C2 extends Parent{
#Override
public void setInteger(){
i = new Integer(2);
}
}
The Output is
stored entity 1
stored entity 2
stored entity 1 <-- ranged for
stored entity 2 <-- ranged for
Edit:
The file structre looks like this
|-MyClass.java
|-lib
|-Parent.java
|-C1.java
|-C2.java
I have a class hierarchy which looks somewhat like this:
class Parent { }
class Child1 extends Parent {}
class Child2 extends Parent {}
class Child3 extends Parent {}
In another class I have methods looking like this:
void doSomething(Parent p) { //default }
void doSomething(Child1 c) { //implementation for Child 1 }
void doSomething(Child2 c) { //implementation for Child 2 }
Currently, when I have something like this
Parent p = new Child2();
doSomething(p);
the first method, doSomething(Parent) is called instead of doSomething(Child2)
Let's assume I have a list of items with the static type of Parent and a dynamic type of ChildN. How can I assure the method, provided for the dynamic type is called, without casting. Only for Child3 (no specific doSomething method) I want to call the default implementation.
What you are looking for is called "multi dispatch or "dynamic dispatch" - and doesn't exist in Java.
In Java, the compiler decides which method to pick in case of overloading. (and that is what happens when you have three methods with the same name but different parameter types). This happens at compile time, and if your "runtime" Parent object happens to be a Child1 object; that doesn't matter. Because the compiler fixed the method to call - as said: java doesn't support dynamic dispatch.
In that sense, the correct Java solution would be to put a method "doSomething()" on your Parent class; and have each child override that method to the specific thing.
In case "doSomething()" doesn't really "fit" into this class; you can have a look into the visitor pattern. Another option would be to use instanceof ... but then you should "hide" the corresponding if/else chain ... again using polymorphism, like:
interface DoIt { void doSomething() }
class ParentDoIt implements DoIt ...
same for Childs
class DoItFactory {
DoIt getDoIt(Parent p) {
if (p instanceof Child1) return new Child1DoIt(p)
...
A solution could be that the doSomething method uses logic from the parameter:
class Parent {
public void neededMethod() {//default}
}
class Child1 {
public void neededMethod() {//implementation for Child 1}
}
Then in your code:
void doSomething(Parent p) {
//more code
p.neededMethod();
// code
}
If this solution does not fit you because you need some kind of a dispatcher, then you will have to use instanceof and then call the proper method:
void doSomething (Parent p) {
if (p instanceof Child1) doSomethingWithChild1(p);
else if (p instanceof Child2) doSomethingWithChild2(p);
...
else defaultSomething(p);
}
I would do it like this.
interface SomeAction { void doSomething(); }
class Parent implements SomeAction { //override doSomething here }
class Child1 extends Parent {//override doSomething here }
class Child2 extends Parent {//override doSomething here }
class Child3 extends Parent { // no need to override here}
Now
In another class I have methods looking like this
void doSomething(SomeAction p) { //default }
Parent p = new Child2();
doSomething(p);
p.doSomething(); // would call Child 2
I have parent class and a child class, both of having a method m1 with same signature (Override), can I call parent class method in following scenario. I dont want to change child class method.
// Super class
public class Parent
{
public void m1()
{
System.out.println("Parent method");
}
}
// Sub class
public class Child extends Parent {
#Override
public void m1() {
System.out.println("Child method");
}
}
// User class
public class Kavi {
public static void main(String[] args) {
Parent p = new Child();
p.m1();
}
}
I want to call parent class m1 method. I know that I can use super in child class method to call its parent method. but I have no right to change the source code of child class. and I have to call it from child class object. please anybody help !!! is it possible in java ??
While creating the Object you are using reference of Super class but your object is of child class, so while calling m1() method the overrided method will be invoked. If you want the method of the super class to be invoked then object should be of Super class. As :
Parent parent=new Parent();
parent.m1();
OR
you can invoke the super class m1() method from the child class.
#Override
public void m1() {
super.m1();
System.out.println("Child method");
}
OR ELSE
import java.lang.reflect.*;
class A {
public void method() {
System.out.println("In a");
}
}
class B extends A {
#Override
public void method() {
System.out.println("In b");
}
}
class M {
public static void main( String ... args ) throws Exception {
A b = new B();
b.method();
b.getClass()
.getSuperclass()
.getMethod("method", new Class[]{} )
.invoke( b.getClass().getSuperclass().newInstance() ,new Object[]{} ) ;
}
}
Without changing the code, you can't do this. You're essentially talking about p.super.m1() which isn't legal in Java. If you want your parent to act like a parent, don't make it a child.
If both parent and child are stateless, you could create a facade over them and explicitly manage the state; this would work, but I wouldn't recommend it.
public class Facade extends Parent {
public enum State {PARENT, CHILD};
private final Child delegate;
private State state = State.CHILD;
public Facade(Child delegate) {
this.delegate = delegate;
}
#Override
public void m1() {
if (State.CHILD == state) {
delegate.m1();
} else {
super.m1();
}
}
public void setState(State state) {
this.state = state;
}
}
This is a purely academic exercise - I can't think of a single good reason to do this in the real world. If you're using an OO language, don't fight the OO paradigm!
I think it not possible. There are two ways to call a parent class method
1.) crate object of parent class as
Parent p = new Parent();
2.) Use super in child class method as
#Override
public void m1() {
super.m1();
System.out.println("Child method");
}
Apart from the already mentioned way, you can declare both the methods as static.
so when you do this
Parent p = new Child();
p.m1();
the static method of parent class would be called and the output will be "Parent method"
Note : The static keyword in Java means that the variable or function is shared between all instances of that class as it belongs to the type, not the actual objects themselves.
So if you have a variable:
private static int i = 0; and you increment it ( i++ ) in one instance, the change will be reflected in all instances.
If you can not use super then instead of creating the child class object you can directly use
Parent p = new Parent();
p.m1();
if you can't even modify the code inside main method then I think it's not possible .
I have the following situation:
A parent class has a function that depends on a constant. But the only valid place to define that constant is in subclasses (parent class cannot define the constant's value, but it can be used with the constant undefined in 99% of use cases - the constant is a default to use if a specific configuration element is missing).
However, I would like to enforce that any child class inheriting from that parent class must define the value for the constant, since any child classes have to be able to use the other 1% of functionality.
What is the best practice to implement this enforcement in Java, ideally at compile time? (clearly, at runtime, I can simply check if the constant is null/empty in the method using it).
My own solution was to implement a value-getter for the constant as an abstract method in the parent class, and call that in combination with the real setter in the constructor; something like this:
public class HelperClass1 {
private String myConstant;
public void setMyConstant() {} // implemented obviousy
public void myMethod() { // Called from ParentClass's methods
// Do something useful with myConstant
}
}
import HelperClass1;
public abstract class ParentClass {
ParentClass() {
HelperClass1.setMyConstant( getMyConstantValue() );
}
public abstract void getMyConstantValue();
}
public class ChildClass1 extends ParentClass {
public void getMyConstantValue() { return "BUZZ"; }
}
public class ChildClass2 extends ParentClass {
} // Fails to compile without getMyConstantValue()
However, (a) This implementation has a problem (I can't use ParentClass itself, since it's now abstract) without subclassing; and (b) since I'm not a Java developer, I'm afraid that this isn't the best or the most elegant solution. So I'd like to know if there's a best practices approach that improves on what I implemented.
Provide two constructors for the parent class:
One is a protected constructor which takes the constant as an argument.
The other is private constructor which can construct instances of the parent class without setting the constant.
Provide a factory method for the parent class which can call the private no-constant constructor.
Classes that want to get an instance of the parent class can call the factory method. But child classes that want to inherit from the parent class have to call the protected constructer, which can validate that a valid constant was passed.
public class ParentClass {
private final SomeClass myConstant;
protected ParentClass(SomeClass aConstant) {
if (null == aConstant) {
throw new IllegalArgumentException("...");
}
myConstant = aConstant;
}
private ParentClass() {
myConstant = null;
}
public static ParentClass getInstance() {
return new ParentClass();
}
}
public class ChildClass {
public ChildClass() {
super(new SomeClass(42));
}
}
This isn't perfect. Someone could write a child class that passes a bad constant to the superclass constructor, and it wouldn't actually fail until some code tried to construct an instance of the child class.
In the following code, the constructor of Child has reduced visibility from public to private, which is allowed. The inherited methods, such as test(), cannot have reduced visibility. Why does Java operate this way?
class Parent {
public Parent(){}
public void test()
{
System.out.print("parent test executed!");
}
}
class Child extends Parent{
private Child(){}
private void test(){
System.out.print("child test executed!");
}
}
Constructors are not inherited, so Child() doesn't override Parent().
As for the methods, if you have (if Child() were public)
Parent p = new Child();
p.test();
Had it been allowed, this would be invoking a private method. So narrowing the access while overriding is not permitted.
When extending a class you are stating that your class is an extension of the parent class ("IS-A" relationship). What this means is that your class will have all methods of your parent class. This is the same as implementing an interface in java except you gain the method definitions (and fields) from your parent and not just methods declared in the interface. In interfaces constructors are not present because they are not methods. Constructors are special as they belong entirely to the class they are declared on. They declare how to construct only themselves.
In order to construct an object you must know that objects class.
class A {
private message;
private A() {
message = "You created an A";
}
public A(String message) {
this.message = message;
}
public void printMessage() {
System.out.println(message);
}
public static A createAnA() {
return new A();
}
}
class B extends A {
public B() {
super("You created a B");
}
}
A anA = new B(); // This will work
A anotherA = new A(); // This is not allowed as the constructor is private
A yetAnotherA = A.createAnA(); // This works too
So when we constructed B we can say that it is an A. Even though the constructor A is private this is due the constructor not being a part of the interface. The only thing we are saying about B when we assign it to a field of type A is that it has the methods of declared in A. In this case printMessage and createAnA.
That is why you can make the constructor private without changing the definition of the class. Now, why are you not allowed to make the method private when overriding a parents signature. This comes to having varying definitions of the [class].method(). Let's say that you could make your method private. Let's say that you declared a printMssage in the B class. Your reasoning is that you want that method for your use only inside the method and you want your parents printMessage to be used when called externally. Now, you wrote a method like this in the B class.
public void adjustMessage(String additional) {
message = getMessage() + additional();
}
Which version of get message would be executed? Your private one or the public one of your parents? The Java dispatcher would of course choose the public one as it is the one declared in the interface. So we we look at this example we can see if you did make your method have different a lower privilege your method could never be dispatched too which would just make things confusing for the reader.
This is a very good question.