使用构造函数的泛型 and/or 对象到 return 超类或子类

Using generics and/or objects of Constructor to return superclass OR subclass

总结:是否可以让不同参数的构造函数在一个方法中创建不同subclasses的对象?


我有一个(非抽象的)class 和一个子class 扩展它。 subclass 有一个附加字段。 两者都是不可变的:

class Superclass{
    final Type type; // Type is an enum; It has a final double decayFactor for each type.
    final int amount;

    Superclass(Type type, int amount){//simple constructor initializing final fields
        ...
    }

    //decay method talked about below is implemented here
}

class Subclass extends Superclass{
    final boolean additionalProperty;

    Subclass(Type type, int amount, boolean additionalProperty){
        super(type, amount);
        this.additionalProperty = additionalProperty;
    }
}

现在我想要一个方法,其中 return 是具有更新数量的相同 class(SubclassSuperclass)的对象。 此方法应按枚举 Type 定义的特定百分比减少 amount。 这个简单的方法可能看起来像那样(在 Superclass 中实现):

public Superclass decay(){
    return new Superclass(type, amount * type.getDecayFactor())
}

现在我的问题是,如果我有一个 Subclass 并调用此方法,将在一个方法中 return 一个 Superclass。我会丢失存储在 additionalProperty 中的信息。 所以我想到了其他方法来解决这个问题。最简单的方法是在 Subclass 中覆盖 decay()。但是,我发现我不能强制 subclass 覆盖此方法。因此,如果稍后添加其他子 classes,如果他们不实现它,可能会发生相同的信息丢失。 所以我试图通过使用泛型来获取 class:

的构造函数来解决这个问题
public <T extends Superclass> Superclass decay() throws ...[Many exceptions]{
    int newAmount = type.getDecayFactor() * amount;
    Constructor<? extends Superclass> constructor = this.getClass().getConstructor(Type.class, int.class);
    return constructor.newInstance(type, amount);
}

我试过了,但未能使用通用 T 而不是 this.getClass()

但是,这也行不通。我仍然必须覆盖它,因为 Subclass(Type, int) 不存在。 我的想法是,如果我能以某种方式获得 class 的所有字段,我可以调用 subclasses 或 superclass 的(唯一)构造函数并传递它需要的所有值, 仅修改量。我试图通过使用 this.getClass().getFields() 来获取匹配的构造函数,但它说: ... getConstructor() ... 不适用于参数字段 []。(我需要字段的类型吗?)

我的问题:这可能吗?这是一个优雅的或受欢迎的实现吗?或者你应该更好地说明 subclasses 必须覆盖 decay(),恕我直言,哪个更简单易读?这里是否需要泛型?(我慢慢开始认为不需要...)

附加信息:我首先将 Superclass 和 Subclass 作为抽象,并且对于每个 Type 枚举自己的 subclass 扩展那些(SuperclassSubclass)。但是我将不得不为每个 classes 编写非常相似的代码。所以我把那些包含的信息放入一个带有最终字段的枚举中。(很容易有 100 个 classes 代表类似的东西)

decay() 方法旨在像这样使用来“修改”不可变的 Superclass/Subclass:

Superclass someObject = newSuperclass/Subclass
...
someObject = someObject.decay();

非常感谢您的回答。

我相信重写该方法应该可以正常工作。您可以更改 decay() 的 return 类型,只要它是 Superclass 的 sub-type。

您还可以在单​​独的方法中隔离计算衰减逻辑以避免冗余代码。

class Superclass {
    final double rate;
    final int amount;

    Superclass(double rate, int amount) {
        this.rate = rate;
        this.amount = amount;
    }

    public Superclass decay() {
        return new Superclass(this.rate, this.calcuateDecay());
    }
    
    protected int calcuateDecay() {
        return (int) (this.amount * this.rate);
    }
}

class Subclass extends Superclass {
    final boolean additionalProperty;

    Subclass(double rate, int amount, boolean additionalProperty) {
        super(rate, amount);
        this.additionalProperty = additionalProperty;
    }
    
    @Override
    public Subclass decay() {
        return new Subclass(this.rate, this.calcuateDecay(), this.additionalProperty);
    }
}

看到它工作 here

在这里覆盖是可选的。为了进一步加强类型安全,泛型接口可以定义如下

interface <T extends Superclass> Decayable<T> {
    T decay();
}

Superclass可以实现Decayable<Superclass>Subclass可以实现Decayable<Subclass>。查看实际效果 here