当对象是基础的实例时,为对象调用正确的方法 class
Calling the correct method for an object, when the object is an instance of a base class
我在 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;
}
说我想用载具做一些工作,而这个工作不依赖于载具的子class。所以,我在另一个 class 中有一个这样的方法:
public void doStuff(public final Vehicle vehicle) {
//do stuff here
//then insert it into my database:
insertVehicle(vehicle);
}
但是,我想在我的 insertVehicle 中做不同的事情,所以我为每个子重写该方法class:
public void insertVehicle(Car car) { //do stuff for a car }
public void insertVehicle(Truck truck) { //do stuff for a truck }
在我的 doStuff 方法中,我可以使用 instanceOf 来确定车辆(Car 或 Truck)的 class,然后将车辆投射到 class 中并像这样调用 insertVehicle 方法:
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 并不是执行此操作的最佳方法。 1
我怎样才能最好地修改它以便我不必使用 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;
}
否则,您可以为 vehicle 添加一个变量,指示车辆类型是什么 return。喜欢:
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' 将在车辆 class 中并将在构造函数中初始化:
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-logic 与 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();
}
这取决于您要解决的问题类型。如果是持久性,请确保您没有重新发明 JPA. If it is type-specific processing then you can solve it as @denis suggested. Or if you want to keep entities in POJO-style you can use strategy pattern,例如:
Map<Class<?>, Consumer<Vehicle>> consumers;
{
consumers.put(Car.class, v -> insertVehicle((Car)v));
consumers.put(Truck.class, v -> insertVehicle((Truck)v));
}
public void doStuff(public final Vehicle vehicle) {
//do stuff here
consumers
.get(vehicle.getClass())
.accept(vehicle);
}
如果您不喜欢将 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
}
}
我在 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;
}
说我想用载具做一些工作,而这个工作不依赖于载具的子class。所以,我在另一个 class 中有一个这样的方法:
public void doStuff(public final Vehicle vehicle) {
//do stuff here
//then insert it into my database:
insertVehicle(vehicle);
}
但是,我想在我的 insertVehicle 中做不同的事情,所以我为每个子重写该方法class:
public void insertVehicle(Car car) { //do stuff for a car }
public void insertVehicle(Truck truck) { //do stuff for a truck }
在我的 doStuff 方法中,我可以使用 instanceOf 来确定车辆(Car 或 Truck)的 class,然后将车辆投射到 class 中并像这样调用 insertVehicle 方法:
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 并不是执行此操作的最佳方法。 1
我怎样才能最好地修改它以便我不必使用 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;
}
否则,您可以为 vehicle 添加一个变量,指示车辆类型是什么 return。喜欢:
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' 将在车辆 class 中并将在构造函数中初始化:
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-logic 与 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();
}
这取决于您要解决的问题类型。如果是持久性,请确保您没有重新发明 JPA. If it is type-specific processing then you can solve it as @denis suggested. Or if you want to keep entities in POJO-style you can use strategy pattern,例如:
Map<Class<?>, Consumer<Vehicle>> consumers;
{
consumers.put(Car.class, v -> insertVehicle((Car)v));
consumers.put(Truck.class, v -> insertVehicle((Truck)v));
}
public void doStuff(public final Vehicle vehicle) {
//do stuff here
consumers
.get(vehicle.getClass())
.accept(vehicle);
}
如果您不喜欢将 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
}
}