我在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);
}
但是,我想在insertVehicle中做不同的事情,所以我为每个子类重写该方法:
public void insertVehicle(Car car) { //do stuff for a car }
public void insertVehicle(Truck truck) { //do stuff for a truck }
在我的doStuff方法中,我可以使用instanceOf来确定车辆的类别(Car或Truck),然后将车辆投射到该类并调用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?
答案 0 :(得分:3)
您可以使用访客模式:
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());
}
}
答案 1 :(得分:3)
您可以在车辆内部进行抽象功能
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'将在车辆类中,并将在构造函数内初始化:
public final class Car extends Vehicle {
public Car(final String name, final String make, final String vehicleType) {
super(name, make, type);
}
}
答案 2 :(得分:1)
这取决于您尝试解决的问题类型。如果是持久性,请确保您没有重新发明JPA。如果是特定类型的处理,那么你可以像@denis建议的那样解决它。或者如果你想保持POJO风格的实体,你可以使用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);
}
答案 3 :(得分:0)
一种方法是在insertVehicle()
中使用Vehicle
方法摘要。然后在子类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();
}
答案 4 :(得分:0)
如果您不想将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);
}
{1}}逻辑转换为另一种方法。
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
}
}
但是,我们可以用泛型做得更好。
X = c(0,1,2,3,4,5)
Y = c("abc", "def", "ghi")
b = data.frame(X, Y)