views:

124

answers:

3

Ok, maybe this is a stupid question. But i'm just wondering if this can be done in java.

abstract public class ParentClass<T> { 
  abstract public T getTest();
}

in the subclass

public class SubClass extends ParentClass<MyObject> {
  public MyObject getTest() {
    // I can return the object with class MyObject
    return null;
  }
}

My question is can I return the class type in the child method? I mean, is it can be done by adding some code in the ParentClass, so I can do this below?

For example

public class Sub1Class extends parentClass<Object1> {
  public Object1 getTest() { }
  // I want to have a method that return it's class in the superclass
  public Sub1Class getItClassObject() { }
}

other example

public class Sub2Class extends parentClass<Object2> {
  public Object2 getTest() { }
  // I want to have a method that return it's class in the superclass
  public Sub2Class getItClassObject() { }
}

one example again

public class Sub3Class extends parentClass<Object3> {
  public Object3 getTest() { }
  // I want to have a method that return it's class in the superclass
  public Sub3Class getItClassObject() { }
}

if you see, method getItClassObject in Sub1Class, Sub2Class and Sub3Class will follow it's class. But I don't want to add same method for every subclass, just want to add some code (if feasible) in the ParentClasss, so in the subclass, I just can call getItClassObject directly without write all the code in every subclass.

Usually I add method in ParentClass like this.

abstract public class ParentClass<T> {
  abstract public T getTest();
  public Object getItClassObject() { }
}

so in the subclass I just instance the class, but I have to cast again :(

Sub1Class sub1Class = new Sub1Class();
Sub1Class after1Cast = (Sub1Class) sub1Class.getItClassObject();

Sub2Class sub2Class = new Sub2Class();
Sub2Class after2Cast = (Sub2Class) sub2Class.getItClassObject();

I think it cannot be done in java. But I don't know if there is a clue to solve this. Thanks

+1  A: 

This is what you want I think. The following compiles:

abstract class A {
    public abstract A getA();
}

class B extends A {
    // Declared to return a B, but it still properly overrides A's method
    @Override
    public B getA() {
        return new B();
    }
}

class C extends A {
    // Declared to return a B, but it still properly overrides A's method
    @Override
    public C getA() {
        return new C();
    }
}

As you can see, A declares that the getA() method returns an A. But, you can restrict the return type in subclasses as shown.

jjnguy
@justin: i know that... but I have to override again for every subclass that I create. I have to override getA return class B for B class, and I have to override getA return class C for C class. Currently in class A, I have method public Object getA() and it's subclass do not need to override. But every method that called in the subclass class, I have to cast again (because return Object)
Jef
@Jef, ah. I see the dilemma. I'm trying to think of a work around...
jjnguy
@justin: yeah... your solution is one of two possible solution (instead of if I have the third solution as I expected). I prefer to use casting rather than your way because I don't need override all of the subclass. Thanks
Jef
@Jef, sorry I couldn't help.
jjnguy
it's ok no prob, thx
Jef
A: 

If your objects have no-arg constructors (or some consistent form of constructor across all of them), you can use reflection to do it. Some pseudocode would be

public class MyClass {

    public MyClass instantiateType() {
       Class<?> actualClass = getClass();
       return actualClass.newInstance();
    }

}

This is using the runtime type of the class, so subclasses will return their type. This works only for a no-arg constructor though.

Jeff Storey
if you have constructor, you can do that too. just type. Class clazz = Class.forName("xxx"); Constructor constructor = clazz.getConstructor(String.class); return constructor.newInstance("i can instance constructor with arg"); That's not what I want
Jef
A: 

I'm not sure if I understand your intent correctly, but I think the built-in Object.getClass() method will do what you want. Given classes defined as:

public abstract class ParentClass<T> {
  public abstract T getTest();
}

class SubClassString extends ParentClass<String> {
   public String getTest() {
      return "";
   }
}

class SubClassInteger extends ParentClass<Integer> {
   public Integer getTest() {
      return Integer.valueOf(0);
   }
}

getClass() will return the correct run-time class

  public static void main(String[] args) {
      SubClassString subString = new SubClassString();
      // displays "class SubClassString"
      System.out.println(subString.getClass()); 

      SubClassInteger subInteger = new SubClassInteger();
      // displays "class SubClassInteger"
      System.out.println(subInteger.getClass());

      ParentClass<?> parentInstance = new SubClassInteger();
      // displays "class SubClassInteger"
      System.out.println(parentInstance.getClass());  
  }
gregcase
I want the method in SubClassString the return value (for method getTest) is Class SubClassString, and the return value in SubClassInteger is SubClassInteger without explicitly have to type it's class. If possible just type the method in the abstract class (once only). I think this cannot be done in java :(
Jef