Search code examples
javamultithreadingsubclasssuperclass

How to construct derived class with existing base class object


i need to construct class for example Apple or Strawberry from existing Fruit object.

This is my Fruit class:

public class Fruit {
    int somevariable;
    Thread somethread;

    public Fruit(int somevariable) {
        this.somevariable = somevariable;

        this.somethread = new Thread() {
            public void run() { /* Something here */ }
        }

        this.somethread.start();
    }

    public Fruit(Fruit fruit) {
        this.somevariable = fruit.somevariable;
        this.somethread = fruit.somethread;
    }
}

And this is my Apple and Strawberry class:

public class Apple extends Fruit {
    public Apple(Fruit fruit) {
        super(fruit);
    }
}

public class Strawberry extends Fruit {
    public Strawberry(Fruit fruit) {
        super(fruit);
    }
}

And i have HashMap like this:

HashMap<Integer, Fruit> fruits = new HashMap<>();

At first, I am adding fruits like this: (All I know is that this is the fruit at the moment. I can't add an apple or a strawberry immediately.)

fruits.put(17, new Fruit(4));
fruits.put(24, new Fruit(8));
fruits.put(95, new Fruit(12));

And when I find out what kind of fruit it is, I need to replace the fruit object with an apple or a strawberry (with same fruit object as super object). Of course without stopping somethread.

And this is how I solve it:

fruits.replace(17, new Strawberry(fruits.get(17)));
fruits.replace(24, new Apple(fruits.get(24)));
fruits.replace(95, new Strawberry(fruits.get(95)));

My questions is:

Can this be made easier? Is my solution correct?

And one more question, if I have functions in a strawberry that are often called from other Threads, how to make sure there is no problem during hashmap value replacement?

Thank you very much for your help :)


Solution

  • Prefer composition to inheritance. Subclassing a concrete class (except Object although that being concrete is sort of kind of being "deprecated" at the moment) isn't usually great.

    Fruit should have a FruitType (or better name). Delegate as necessary.

    Also note, in the original code, that the Runnable (Edit: Thread with naught overridden run) will have been created in the context of the original Fruit instance. Also also, the thread will initially see a Fruit that is not guaranteed to be fully initialised.