Java 我可以将对象从子类传递到抽象类吗?
这是我的抽象类AbstractVehicles,它实现了Vehicles接口Java 我可以将对象从子类传递到抽象类吗?,java,oop,design-patterns,Java,Oop,Design Patterns,这是我的抽象类AbstractVehicles,它实现了Vehicles接口 public abstract class AbstractVehicles implements Vehicles{ } 这是我的名片 public class CarImpl extends AbstractVehicles implements Car { private CarAI ai; private static final int CAR_FUEL_LEFT = 10; pu
public abstract class AbstractVehicles implements Vehicles{
}
这是我的名片
public class CarImpl extends AbstractVehicles implements Car {
private CarAI ai;
private static final int CAR_FUEL_LEFT = 10;
public CarImpl(){
super(FUEL_LEFT);
this.ai = new CarAI();
}
public void move(World w){
// AI is using here
ai.act(w);
}
}
这是我的自行车
public class BicycleImpl extends AbstractVehicles implements Bicycle {
private BicycleAI ai;
private static final int BICYCLE_FUEL_LEFT = 10;
public BicycleImpl(){
super(BICYCLE_FUEL_LEFT);
this.ai = new BicycleAI();
}
public void move(World w){
// AI is using here
ai.act(w);
}
}
其中,汽车和自行车的接口是
public interface Car extends Vehicles {
}
public interface Bicycle extends Vehicles {
}
问题来了
我在其他包中分别实现了汽车和自行车的AI
叫BicycleAI和CarAI。但是它们的CarImpl和BicycleImpl中的代码是相同的。
所以我想将其添加到抽象类中,以便代码可以重用。
BicycleAI类和CarAI类实现了接口AI
正如我们在上面看到的,他们的act代码是相同的,但是AI对象是不同的。
我可以把这段代码放到抽象类中吗
我试着这么做
public abstract class AbstractVehicles implements Vehicles{
protected AI ai;
private int fuelLeft;
public AbstractVehicles(int fuelLeft){
this.fuleLeft = fuelLeft
AI ai = new AI();
}
public void move(World w){
ai.act(w); // But I have no idea this is CarAI or BicycleAI
}
}
我对AbstractVehicles中的构造函数和RabbitImpl中的构造函数有点困惑。
如果我创建一个对象RabbitImpl,我调用move 指混凝土等级。因此this.ai或ai是对实际实现类字段的引用。是指具体类。因此this.ai或ai是对实际实现类字段的引用。您可以使用模板方法模式,其中超类通过使用抽象方法将某些步骤推迟到其子类。在这里,您将委托给子类的步骤是提供实际的AI实现,供您希望子类共享的其余父抽象类代码使用
public abstract class AbstractVehicles implements Vehicles{
protected AI ai;
public AbstractVehicles(){
AI ai = initAI();
}
protected abstract AI initAI(); // template method
public void move(World w){
ai.act(w); // But I have no idea this is CarAI or BicycleAI
}
}
现在,您的Car和Bicycle类将提供如下模板实现
public class CarImpl extends AbstractVehicles implements Car {
protected AI initAI() {
return new CarAI();
}
}
public class BicycleImpl extends AbstractVehicles implements Car {
protected AI initAI() {
return new BicycleAI();
}
}
您可以使用模板方法模式,其中超类通过使用抽象方法将某些步骤推迟到其子类。在这里,您将委托给子类的步骤是提供实际的AI实现,供您希望子类共享的其余父抽象类代码使用
public abstract class AbstractVehicles implements Vehicles{
protected AI ai;
public AbstractVehicles(){
AI ai = initAI();
}
protected abstract AI initAI(); // template method
public void move(World w){
ai.act(w); // But I have no idea this is CarAI or BicycleAI
}
}
现在,您的Car和Bicycle类将提供如下模板实现
public class CarImpl extends AbstractVehicles implements Car {
protected AI initAI() {
return new CarAI();
}
}
public class BicycleImpl extends AbstractVehicles implements Car {
protected AI initAI() {
return new BicycleAI();
}
}
将AI传递给抽象类的构造函数
public abstract class AbstractVehicles implements Vehicles{
protected final AI ai;
public AbstractVehicles(AI ai){
this.ai = ai;
}
public void move(World w){
ai.act(w);
}
}
public class CarImpl extends AbstractVehicles implements Car {
public CarImpl(){
super(new CarAI());
}
}
将AI传递给抽象类的构造函数
public abstract class AbstractVehicles implements Vehicles{
protected final AI ai;
public AbstractVehicles(AI ai){
this.ai = ai;
}
public void move(World w){
ai.act(w);
}
}
public class CarImpl extends AbstractVehicles implements Car {
public CarImpl(){
super(new CarAI());
}
}
除了抽象AI之外,您还可以使用模板使其了解细节
public abstract class AbstractVehicles<AI extends AbstractAI> implements Vehicles {
protected AI ai;
public AbstractVehicles(AI ai){
this.ai = ai;
}
public void move(World w){
ai.move(w);
}
}
当然,这种设计的缺陷在于,您不能准确地获取泛型类并在抽象类中构造它。但是,对于子类,您可以很好地做到这一点
public abstract class CarImpl extends AbstractVehicles<CarAI> implements Car{
public CarImpl(){
super(new CarAI());
}
}
通过这样做,CarImpl中的所有AI引用都将被识别为CarAI,这要归功于泛型输入。除了抽象AI之外,您还可以使用模板来了解细节
public abstract class AbstractVehicles<AI extends AbstractAI> implements Vehicles {
protected AI ai;
public AbstractVehicles(AI ai){
this.ai = ai;
}
public void move(World w){
ai.move(w);
}
}
当然,这种设计的缺陷在于,您不能准确地获取泛型类并在抽象类中构造它。但是,对于子类,您可以很好地做到这一点
public abstract class CarImpl extends AbstractVehicles<CarAI> implements Car{
public CarImpl(){
super(new CarAI());
}
}
通过这样做,CarImpl中的所有AI引用都将识别为CarAI,这要归功于泛型键入。实际上,您可以将move放入AbstractVehicles中。抽象类可以有具体的方法。那么,您尝试的方法出了什么问题?您的CarAI或BicycleAI是AI的子类吗?那么,如果我创建一个RabbitImpl对象,并调用move,它将在抽象类中运行代码move?但我也在抽象载体中定义了一个构造器AI。这合适吗?CarAI和BycycleAI暗示AI。人工智能是一个界面,你可以把移动放在抽象的交通工具里。抽象类可以有具体的方法。那么,您尝试的方法出了什么问题?您的CarAI或BicycleAI是AI的子类吗?那么,如果我创建一个RabbitImpl对象,并调用move,它将在抽象类中运行代码move?但我也在抽象载体中定义了一个构造器AI。这合适吗?CarAI和BycycleAI暗示AI。人工智能是一个非常适合你的界面。但是当我这么做的时候,他们需要我的人工智能先回到CarAI?以后,请不要为了问问题而编辑答案。非常感谢。但是当我这样做的时候,他们需要我的人工智能先回到CarAI?以后,请不要为了问一个问题而编辑答案。事实上,这被认为是非常糟糕的做法。永远不要从构造函数调用非final方法。如果抽象调用该方法,则情况更糟。这是因为该方法是在构造函数尚未完成的类中调用的。如果重写方法依赖于构造函数中初始化的任何字段,则很可能会失败。@JohnB,重写的唯一目的是在此处提供一个实例。它不依赖于对象当前所处的状态。不管是什么原因,从构造函数调用非final方法是非常糟糕的做法,尤其是已知被重写的方法。这不是一个模式,不应该作为一个例子来做什么。鉴于所问的问题,最好将实例传递给构造函数。@JohnB,不,不管原因是什么!方法不能同时是抽象的和最终的
除了实例化必要的实现之外,不需要做任何其他事情。像Spring这样的容器总是实例化一个未完成的bean,然后通过setter注入它的依赖项以使其完整。框架总是发出回调来获取一个他们不知道其类型的实例;构造函数在这里也在做同样的事情。因此,除非你提供了一个很好的理由,说明这种方法可能会在哪里失败;输入大写字母对讨论没有多大帮助。事实上,这被认为是非常糟糕的做法。永远不要从构造函数调用非final方法。如果抽象调用该方法,则情况更糟。这是因为该方法是在构造函数尚未完成的类中调用的。如果重写方法依赖于构造函数中初始化的任何字段,则很可能会失败。@JohnB,重写的唯一目的是在此处提供一个实例。它不依赖于对象当前所处的状态。不管是什么原因,从构造函数调用非final方法是非常糟糕的做法,尤其是已知被重写的方法。这不是一个模式,不应该作为一个例子来做什么。鉴于所问的问题,最好将实例传递给构造函数。@JohnB,不,不管原因是什么!该方法不能同时是抽象的和最终的,并且除了实例化必要的实现之外,不需要做任何其他事情。像Spring这样的容器总是实例化一个未完成的bean,然后通过setter注入它的依赖项以使其完整。框架总是发出回调来获取一个他们不知道其类型的实例;构造函数在这里也在做同样的事情。因此,除非你提供了一个很好的理由,说明这种方法可能会在哪里失败;输入大写字母对讨论没有多大帮助。