Java 使用泛型和/或构造函数的对象返回超类或子类

Java 使用泛型和/或构造函数的对象返回超类或子类,java,constructor,subclass,Java,Constructor,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){//si

小结:可以让具有不同参数的构造函数在一个方法中创建不同子类的对象吗


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

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;
    }
}
现在我想要一个方法,它返回一个相同类(
子类
超类
)的对象,并更新数量。 此方法应将
金额
减少由enum
类型
定义的特定百分比。 这个简单的方法可能是这样的(在
超类中实现):

现在我的问题是,如果我有一个
子类
,并调用这个方法,就会在一个方法中返回一个
超类
。我将丢失存储在
additionalProperty
中的信息。 所以我想了其他方法来解决这个问题。最简单的方法是覆盖
子类
中的
decay()
。但是,我发现我不能强制子类重写这个方法。因此,如果以后添加其他子类,如果它们不实现它,同样的信息丢失也会发生。 所以我试图通过使用泛型来获得类的构造函数来解决这个问题:

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);
}

非常感谢您的回答。

我认为重写该方法应该可以很好地工作。您可以更改
decay()
的返回类型,只要它是
超类的子类型

您还可以在单独的方法中隔离计算衰减逻辑,以避免重复代码

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);
    }
}
看到它工作

在这里重写是可选的。为了进一步加强类型安全性,通用接口可以定义如下

interface <T extends Superclass> Decayable<T> {
    T decay();
}
接口可衰减{
T衰减();
}

超类
可以实现
Decayable
子类
可以实现
Decayable
。查看它的实际操作。

为什么不能重载decay()方法?您可以更改其返回类型,只要它是超类或它的子类之一。因此,您会说,通常在文档中添加注释就足以覆盖此方法,而不是尝试生成更复杂的代码?这个问题只来自我的一个私人项目。但我想说的是,我正在努力学习良好的代码实践。从技术上讲,覆盖不是强制性的。如果未提供任何实例,
decay()
将返回“超类”的实例。添加注释会鼓励代码的未来用户重写该方法。强调子类返回完全相同的子类类型需要更多的代码,我认为这是没有必要的。我更新了我的答案以反映这一点。
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);
    }
}
interface <T extends Superclass> Decayable<T> {
    T decay();
}