Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当对象是基类的实例时,调用对象的正确方法_Java_Polymorphism_Subclassing - Fatal编程技术网

Java 当对象是基类的实例时,调用对象的正确方法

Java 当对象是基类的实例时,调用对象的正确方法,java,polymorphism,subclassing,Java,Polymorphism,Subclassing,我有以下Java示例: public abstract class Vehicle { private final String name; private final String make; public Vehicle(final String name, final String make) { this.make = make; this.name = name; } } public final class Car

我有以下Java示例:

public abstract class Vehicle {
    private final String name;
    private final String make;

    public Vehicle(final String name, final String make) {
        this.make = make;
        this.name = name;
    }
}

public final class Car extends Vehicle {
    public Car(final String name, final String make) {
        super(name, make);
    }
}

public final class Truck extends Vehicle  {
    final Integer grossVehicleWeight;

    public Truck(final String name, final String make, final Integer gvw) {
        super(name, make);
        this.grossVehicleWeight = gvw;
}
假设我想用一辆车做一些工作,工作不依赖于车的子类。我在另一个类中有一个方法,如下所示:

public void doStuff(public final Vehicle vehicle) {
    //do stuff here
    //then insert it into my database:
    insertVehicle(vehicle);
}
public void doStuff(public final Vehicle vehicle) {
    //do stuff here
    //then insert it into my database:
    if (vehicle instanceof Car) {
        insertVehicle((Car) vehicle);
    } else {
        insertVehicle((truck) vehicle);
    }
}
但是,我希望在insertVehicle中执行不同的操作,因此我为每个子类重写该方法:

public void insertVehicle(Car car) { //do stuff for a car }

public void insertVehicle(Truck truck) { //do stuff for a truck }
在我的doStuff方法中,我可以使用instanceOf来确定车辆的类别(汽车或卡车),然后将车辆强制转换到该类别中,并调用insertVehicle方法,如下所示:

public void doStuff(public final Vehicle vehicle) {
    //do stuff here
    //then insert it into my database:
    insertVehicle(vehicle);
}
public void doStuff(public final Vehicle vehicle) {
    //do stuff here
    //then insert it into my database:
    if (vehicle instanceof Car) {
        insertVehicle((Car) vehicle);
    } else {
        insertVehicle((truck) vehicle);
    }
}
然而,我读到使用instanceof并不是最好的方法


我如何才能最好地修改它,从而不必使用instanceof?

您可以使用访问者模式:

public interface VehicleVisitor {
    public void visit(Car car);
    public void visit(Truck truck);
}

public class Car extends Vehicle {

    @Override
    public void insert(VehicleVisitor vehicleVisitor) {
        vehicleVisitor.visit(this);
    }
}

public class Truck extends Vehicle {
    @Override
    public void insert(VehicleVisitor vehicleVisitor) {
        vehicleVisitor.visit(this);
    }
}

public abstract class Vehicle {
    public abstract void insert(VehicleVisitor vehicleVisitor);
}

public class VehicleVisitorImpl implements VehicleVisitor {

    @Override
    public void visit(Car car) {
        System.out.println("insert car");
    }

    @Override
    public void visit(Truck truck) {
        System.out.println("insert truck");
    }
}

public class Main {

    public static void main(String[] args) {
        Vehicle vehicle = new Car();
        // finally the agnostic call
        vehicle.insert(new VehicleVisitorImpl());
    }

}

您可以在车辆内部创建抽象函数

public abstract void doStuff()
从要修改的对象实例调用此函数

ford.doStuff();     //ford is car instance 
然后你可以用这个来修改

doStuff()
{
    this.cost += 10;
}
否则,您可以为车辆添加一个指示车辆类型的变量,并返回该变量。比如:

  public void doStuff(public final Vehicle vehicle) {
       //do stuff here
       //then insert it into my database:
       if (vehicle.getType()== 'Car') {
            insertVehicle((Car) vehicle);
        } else {
            insertVehicle((truck) vehicle);
        }
   }
此变量“vehicleType”将位于vehicle类中,并将在构造函数中初始化:

  public final class Car extends Vehicle {
       public Car(final String name, final String make, final String vehicleType) {
             super(name, make, type);
        }
    }

一种方法是在
Vehicle
中抽象
insertVehicle()
方法。然后在子类
Car
Truck
中实现它们

但是,这会将逻辑移到POJO中。也许最好将db逻辑与POJO分开,即在这种情况下只使用
instanceof

public abstract class Vehicle {
    private final String name;
    private final String make;

    public Vehicle(final String name, final String make) {
        this.make = make;
        this.name = name;
    }

    public abstract void insertVehicle();
}

public final class Car extends Vehicle {
    public Car(final String name, final String make) {
        super(name, make);
    }

    public void insertVehicle() {

    }
}

public final  class Truck extends Vehicle {
    final Integer grossVehicleWeight;

    public Truck(final String name, final String make, final Integer gvw) {
        super(name, make);
        this.grossVehicleWeight = gvw;
    }

    public void insertVehicle() {

    }
}

public void doStuff(Vehicle vehicle) {
    //do stuff here
    //then insert it into my database:
    vehicle.insertVehicle();
}

这取决于你想解决什么样的问题。如果是坚持,请确保你没有重新创造。如果它是特定类型的处理,那么您可以按照@denis的建议解决它。或者,如果要保持POJO样式的实体,可以使用以下命令:


Map如果您不喜欢将
doStuff()
放入
Car
Truck
中,您可以为它们中的每一个设置
doStuff()
方法,并将通用的
Vehicle
逻辑放入另一个方法中

private void doCommonStuff(final Vehicle vehicle) {
    //do stuff here
}

public void doStuff(final Car car) {
    doCommonStuff(car);
    //then insert it into my database:
    insertVehicle(car);
}

public void doStuff(final Truck truck) {
    doCommonStuff(truck);
    //then insert it into my database:
    insertVehicle(truck);
}
不过,我们可以用泛型做得更好

public abstract class StuffDoer<T extends Vehicle> {
  public void doStuff(final T vehicle) {
    // do stuff here
    // then insert it into my database:
    insertVehicle(vehicle);
  }

  public abstract void insertVehicle(T vehicle);
}

public class CarStuffDoer extends StuffDoer<Car> {
  public void insertVehicle(Car car) {
    // whatever
  }
}

public class TruckStuffDoer extends StuffDoer<Truck> {
  public void insertVehicle(Truck truck) {
    // whatever else
  }
}
公共抽象类StuffDoer{
公共车辆(最终T型车辆){
//在这里做事
//然后将其插入我的数据库:
插入车辆(车辆);
}
公共车辆(T型车辆);
}
公共类CarStuffDoer扩展了StuffDoer{
公共车辆(汽车){
//随便
}
}
公共类TruckStuffDoer扩展了StuffDoer{
公共车辆(卡车){
//还有别的吗
}
}

这些insertVehicle方法的作用是什么?OO实现这一点的方法是使insertVehicle(或此方法的特定部分)成为Vehicle的实例方法,在每个子类中重写。或者使用访问者模式。发布代码以获得更具体的帮助。