Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.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_Oop_Design Patterns - Fatal编程技术网

Java 我可以将对象从子类传递到抽象类吗?

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

这是我的抽象类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;
    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注入它的依赖项以使其完整。框架总是发出回调来获取一个他们不知道其类型的实例;构造函数在这里也在做同样的事情。因此,除非你提供了一个很好的理由,说明这种方法可能会在哪里失败;输入大写字母对讨论没有多大帮助。