重用继承来定义Java中的方法

时间:2017-06-04 21:47:16

标签: java generics inheritance

我是一名新的Java开发人员,我在java中继承概念遇到了一些困难来定义我的类......

在一方面,我有一个名为 Vehicle 的通用类,它定义了数十年的属性(使用其getter / setter)。我有一个 Vehicle1 扩展车辆类。

另一方面,我有一个名为 VehicleFactory 的通用classe,它定义了一个这样的静态方法:

public class VehicleFactory {

    protected static Vehicle makeResult() {
        Vehicle result = new Vehicle();

        result.setCode("1");
        result.setNumber("2");
        // other setters methods
        return result;
    }

问题是我想用自己的makeResult方法创建一个 Vehicle1Factory 类,该方法使用其父类的makeResult方法。但我没有做到这一点(这里的目标是优化,因为Vehicle1具有Vehicle classe的所有通用属性,但有一些额外的属性)。

我试着写的是这样的:

public class Vehicle1Factory extends VehicleFactory {

    protected static Vehicle1 makeResult() {
        Vehicle1 result = new Vehicle1();

         result = (Vehicle1) VehicleFactory.makeResult();

        // I want to reuse the makeResult of its parent class to define
        // its own makeResult method
    }
}

但是当我这样做时,Java告诉我有一个ClassCastException并且我不能在这里使用演员......

那种情况有解决方案吗?

4 个答案:

答案 0 :(得分:1)

创建Something的实例后,它永远不会成为其他内容的实例。由于VehicleFactory.makeResult创建了Vehicle个实例,因此无法将其转换为Vehicle1。 您必须为此创建new Vehicle1

解决方案可以是将您要重用的代码移动到实用程序方法,例如:

class Vehicle { }

class Bike extends Vehicle { }

class VehicleFactory {
    static Vehicle create() {
        Vehicle vehicle = new Vehicle();
        initialize(vehicle);
        return vehicle;
    }

    private static void initialize(Vehicle vehicle) {
        result.setCode("1");
        result.setNumber("2");
        // ...
    }
}

class BikeFactory {
    static Bike create() {
        Bike bike = new Bike();
        VehicleFactory.initialize(bike);
        return bike;
    }
}

答案 1 :(得分:0)

发生

ClassCastException是因为您正在尝试将Vehicle投放到Vehicle1;

为什么你不能这样做?因为如果对象类型在Vehicle1引用类型下为Vehicle,您可以将其强制转换。

public class Vehicle1Factory extends VehicleFactory {

    protected static Vehicle1 makeResult() {
        // Change reference type to Vehicle 
        Vehicle result = VehicleFactory.makeResult();

        // I want to reuse the makeResult of its parent class to define
        // its own makeResult method
    }
}

让我们试着澄清一下铸造的所有黑暗点。

Super sub1 = new Sub(); // No casting required!
Super super1 = new Super();
Sub sub2 = new Sub();
sub2 = (Sub) sub1; // Casting required, because reference type is Super, but it's okay because real object under the reference is Sub();
sub2 = (Sub) super1(); // ClassCastException because real object is of Super type

最后一行的演员告诉编译器不要担心,我是一个优秀的程序员,我知道我在做什么,超类引用引用的对象实际上是在运行时的Sub类。所以没有编译时错误。但是在运行时,这会失败,因为实际对象不是Sub,而是Super

答案 2 :(得分:0)

由于已经回答了ClassCastException问题。我想就如何设置抽象提出一些意见。

1)在抽象类中定义抽象工厂概念通常是个好主意。

2)我没有看到“保护”和“静止”在一起​​的意义。除非您的类仅由同一包中的子类和类使用。

3)扩展具体类并仅使用其静态方法没有意义。将静态和继承混合在一起通常是一种不好的做法。

无论如何,这里是带有更清晰抽象定义的示例代码:

 public class Vehicle {
    private int code = 0;
    private int number = 0;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}

public class Vehicle1 extends Vehicle {
    private String engine = null;

    public String getEngine() {
        return engine;
    }

    public void setEngine(String engine) {
        this.engine = engine;
    }
}

public abstract class AbstractVehicleFactory<T extends Vehicle> {

    protected T makeVehicle() {
        T result = create();

        result.setCode(11);
        result.setNumber(24);

        return result;
    }

    protected abstract T create();
}

public class VehicleFactory extends AbstractVehicleFactory<Vehicle> {

    public static Vehicle makeResult(){
        return new VehicleFactory().makeVehicle();
    }

    @Override
    protected Vehicle makeVehicle() {
        Vehicle result = super.makeVehicle();
        return result;
    }

    @Override
    protected Vehicle create(){
        return new Vehicle();
    }
}

public class Vehicle1Factory extends AbstractVehicleFactory<Vehicle1> {

    public static Vehicle1 makeResult(){
        return new Vehicle1Factory().makeVehicle();
    }

    @Override
    protected Vehicle1 makeVehicle() {
        Vehicle1 result = super.makeVehicle();

        result.setEngine("V8");

        return result;
    }

    @Override
    protected Vehicle1 create(){
        return new Vehicle1();
    }
}

答案 3 :(得分:0)

问题是一个向下倾斜的问题。认为您在Vehicle中有X和Y参数,但在Vehicle1中添加了Z参数。 Vehicle1将其中的所有3个作为其车辆的女儿。当您将其投射到Vehicle时,它只是隐藏了Z的引用,但是当您将Vehicle转换为Vehicle1时,由于未为Vehicle1初始化Z变量,因此会发生转换问题。

在方法中初始化vehicle1并设置参数。如

public class 

    Vehicle1Factory extends VehicleFactory {

    protected static Vehicle1 makeResult(){
        Vehicle1 result = new Vehicle1();
        Vehicle veh = (Vehicle1) VehicleFactory.makeResult();
        result.setCode(veh.getCode);
        result.setNumber(veh.getNumber);
        return result;
    }
}