如何使用现有基础 class 对象构造派生 class

How to construct derived class with existing base class object

我需要从现有的 Fruit 对象构造 class 例如 Apple 或 Strawberry。

这是我的水果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;
    }
}

这是我的苹果和草莓class:

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

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

我有这样的 HashMap:

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

起初,我是这样添加水果的: (我只知道现在是这个水果,我不能马上加一个苹果或者一个草莓。)

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

当我发现它是哪种水果时,我需要用苹果或草莓替换水果对象(与超级对象相同的水果对象)。当然没有停止somethread。

我就是这样解决的:

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

我的问题是:

这可以变得更简单吗?我的解决方案正确吗?

还有一个问题,如果我在一个草莓中有经常被其他线程调用的函数,如何确保在替换hashmap值时没有问题?

非常感谢您的帮助:)

至于并发修改使用Collections.synchronizedMap或者ConcurrentHashMap.

至于制作更容易,你能具体说明你想让什么更容易吗?不必编写构造函数?

回答问题“这可以更简单吗?我的解决方案正确吗?

是的。你根本不必在这里做 replace 因为你放在地图中的对象是 Fruit 类型,当你需要对其进行操作时就可以转换它。

如果您希望更具体,也可以像 obj instanceof Fruit 这样检查。

此外,正如@miszcz2137 也提到的那样,您的代码看起来一点也不安全,并发修改 迫在眉睫。

优先组合而不是继承。 子class具体class(Object除外,尽管具体是一种"deprecated" 目前)通常不是很好。

Fruit 应该有一个 FruitType(或更好的名称)。根据需要委派。

另请注意,在原始代码中,Runnable编辑: Thread 没有被覆盖 run)在原始 Fruit 实例的上下文中创建。此外,该线程最初会看到 Fruit 不能保证完全初始化。