Harry Muscle
Harry Muscle

Reputation: 2377

Create a parent class that returns child class objects

I'm building a base/parent class in Java that's going to have several methods for creating the class itself and I'm wondering if there's any way to have the parent class return instances of the child class instead of returning instances of the parent class that then have to be cast to the child?

For example, here's my parent class:

public abstract class SFObject
{
  // Variables
  protected String mID;
  protected String mName;

  // Function called to create ourselves from a DiffObject
  public abstract SFObject CreateFromDiffObject(DiffObject object);

  // Function called to create a list of ourselves from a query
  public List<SFObject> CreateListFromQuery(Connection connection, String query)
  {
    // Run the query and loop through the results
    ArrayList<SFObject> objects = new ArrayList<SFObject>();
    for (DiffObject object : connection.Query(query))
      objects.add(CreateFromDiffObject(object));

    return objects;
  }
}

If I create a child class based on my SFObject class, the two functions in my child class will still return an SFObject (that needs to be cast to my child class type) or a list of SFObjects (that need to be individually cast to my child class type). Is there any way (maybe using Reflections) to have my child class returns instances of itself as itself and not as SFObjects?

Upvotes: 3

Views: 6197

Answers (4)

Jim Garrison
Jim Garrison

Reputation: 86774

What you are describing is known as a covariant return type.

Class A {
    A getInstance() { ... }
}

Class B extends A {
    @Override
    B getInstance() { ... }
}

This has been allowed since Java 1.5.

Upvotes: 1

Francisco Spaeth
Francisco Spaeth

Reputation: 23903

Exactly for this functionalities are proposed the factory methods, as you already implemented. In the child class you can change the return type without offending the method declaration. A sample for your case would be something like:

public abstract class SFObject {
    // Variables
    protected String mID;
    protected String mName;

    // Function called to create ourselves from a DiffObject
    public abstract SFObject CreateFromDiffObject(DiffObject object);

    // Function called to create a list of ourselves from a query
    public List<? extends SFObject> CreateListFromQuery(Connection connection, String query) {
        // Run the query and loop through the results
        ArrayList<SFObject> objects = new ArrayList<SFObject>();
        for (DiffObject object : connection.Query(query))
            objects.add(CreateFromDiffObject(object));

        return objects;
    }

}

class SFObjectChild extends SFObject {

    @Override
    public SFObjectChild CreateFromDiffObject(DiffObject object) {
        SFObjectChild result = new SFObjectChild();
        //...
        return result;
    }

    @Override
    public List<? extends SFObjectChild> CreateListFromQuery(Connection connection,
            String query) {
        return null;//..;
    }

}

This is acceptable because the return type of the children class is still a kind of (hierarchical speaking) the parent.

Be aware of java code conventions (methods in camel case starting with low, e.g. createFromDiffObject).

Upvotes: 0

Devolus
Devolus

Reputation: 22084

Not sure if I really understand your Problem correct because it sounds to me lke this:

class p
{
    public static p createParent()
    {
        return new p();
    }

    public static c createChild()
    {
        return new c();
    }
}

Of course it doesn't have to be static, just thought of some kind of factory.

Upvotes: 0

myacobucci
myacobucci

Reputation: 185

If you place the child class object inside of the parent object, methods called will run from the child class. But it will look like the parent object on the surface

public class A{
    method 1(){//do some stuff}
    method 2(){//do some stuff}
}

public class B extends A{
    method 1(){super.method 1()
    //do some other stuff}
    method 2(){super.method 2()
    //do some other stuff}
}

public class test{
  A a = new B();

 //any method called on 'a' will come from the child class
 // But 'a' is the parent object

}

Upvotes: 0

Related Questions