简体   繁体   中英

Specifying which subclass in super class constructor

I am trying to first populate a list of generic objects and later instantiate them, and when instantiating them, specify which of the objects each is.

The use-case I am working on is reading a data file and constructing a map, which has various interactable objects. The type of interactable each object is is stored in it's own data file that is directed from the map's data file. Some code for example:

in reading the map:

    if ((char)map[i][j] == '*')
           mapObjects.add(new MapObject());

and afterward:

    for (int i = 0 ; i < mapObjects.size() ; i++)
            mapObjects.set (i, new MapObject(in.readLine())); 
            //in.readLine gives the path for the file

in MapObject's constructor:

    public MapObject (String in){
    try{
        BufferedReader br = new BufferedReader(new FileReader("src/data/" + in + ".txt"));
        int temp = Integer.parseInt(br.readLine());
        if (temp == 0)
            this = new Door (); //this is apparently not allowed

            /*continue to instantiate the Door's fields from the data file*/
    }

and the Door class:

    public class Door extends MapObject {
        public Door () {}
    }

I realize that this probably isn't the best way to solve this problem, but it raised the curiosity that this doesn't work. Is there any way to do this? Have the super's constructor choose which subclass it will be?

Not possible. Because subclass constructor must be invoked first, and it (explicitly or implicitly) calls super class constructor. So Door's (for example) constructor MUST have already been invoked before the super class instructor, if this is to be an instance of Door.

Parent/child are not correct terms here. You seem to be talking about a class and one or more subclasses.

Responding to edited question:

You probably want to replace the MapObject constructor with a MapObject factory. Search for factory pattern or static factory method pattern.

What you want is the Abstract Factory pattern .

Briefly...

It's poor design to have a superclass know about subclasses, but it's OK to have a separate class that knows about both.

The abstract factory defines a factory method that returns the abstract type (an interface or a superclass - in this case MapObject) and the method decides which exact class will be returned based on the parameters to the method.

A simple example would be:

public class MapObjectFactory {

    public MapObject create(int i) {
        if (i == 0)
            return new Door();
        if (i == 1)
            return new OtherSubClass();
        // etc, then a "default" in case above conditions not met
        return new MapObject();
    }
}

Then to invoke:

MapObjectFactory factory = new MapObjectFactory();

MapObject m = factory.create(Integer.parseInt(br.readLine()));

You could make the create() method static to avoid having to create an instance of MapObjectFactory just to invoke what is a stateless method:

MapObject m = MapObjectFactory.create(Integer.parseInt(br.readLine()));

but then you couldn't swap in another implementation at runtime in case you wanted to make the selection criteria dynamic. In this case you'd make the factory class implement an interface and make load it using a class name for example (or even have an abstract factory for the abstract factory!).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM