学习接口和层次结构,放置某些变量和方法的位置?

时间:2016-04-22 16:42:00

标签: java inheritance interface abstract class-hierarchy

因此,作为汽车租赁系统的一部分,我需要编写代表大型和小型汽车的课程,这些之间的区别在于它们具有不同尺寸的坦克并以不同的速率消耗燃料。目前我的方法是有一个接口Car,由一个抽象类AbstractCar实现,它由两个具体的类SmallCar和LargeCar扩展。然而,这是我第一次使用接口和抽象类(我们只是在课堂上介绍它们,这项任务旨在评估我们对它们的了解),而且我很难知道在什么课程中放置什么。

fill方法实现完全相同,只需要引用FUEL_CAPACITY的正确值,所以我觉得我应该在AbstractCar类中实现这些方法,但后来我不知道如何获取它们引用正确的FUEL_CAPACITY值。现场fuelLevel显然也被所有汽车所控制,因此我觉得我应该在AbstractCar中声明它,但是我不能在不删除其隐私的情况下从子类访问它。

有人能帮助我弄清楚我做错了什么或误解了接口和继承吗?我一直在考虑的一件事是生成一个枚举CarType,让AbstractCar将CarType作为一个字段,所有实现都在AbstractCar类中完成,使用if语句切换到正确的FUEL_CAPACITY值,并简单地使用SmallCar和LargeCar作为构造函数或者工厂类没有太多甚至任何实际的实现。

提前感谢任何帮助,我意识到它有点长,但我努力确保我完全理解我们正在学习的概念,并且我正确地实现它们而不是仅仅将一些“有效” '但可能不一定是正确或最优雅的解决方案。

3 个答案:

答案 0 :(得分:1)

您可以使用您指出的值将逻辑传输到AbstractCar。然后只需在SmallCar和LargeCar的构造函数中设置这些值。这将是一种方法。就像你指出的那样,你总是必须在父类中有共同的逻辑。您希望避免重复的代码。然后你只需要确保在构造函数中设置不同的值。如果您知道修复值(就像您在给定示例中所做的那样),您甚至可以省略为SmallCar或LargeCar构造函数提供参数,并在构造函数内的super()调用中设置这些固定值。

以下是我的解决方案的实施。

接口Car,其中我删除了getFuelMethod()方法,因为访问级别必须受到保护:

public interface Car {

  RegistrationNumber getRegistration();

  int getFuelCapacity();

  // int getFuelLevel(); this can not be implemented
  // all methods in an interface are PUBLIC
  // so you have to lower the access level by removing it from the interface

  // HERE goes the rest of the method signatures

}

}

抽象类AbstractCar

public abstract class AbstractCar implements Car {
  // this is the common variable
  // that is why we save it in the parent class
  private int fuelCapacity;

  private int fuelLevel;

  // we forward the value to the parent constructor with the super call
  public AbstractCar(int fuelCapacity) {
    this.fuelCapacity = fuelCapacity;
    // I set the value to 0 for the start, but
    // you can also pass the value to the super call,
    // same as fuelCapacity - it is up to you
    this.fuelLevel = 0;
  }

  // The getters and setter allow us to retrieve the values
  // from the abstract class through capsulation!

  // here we have the getter to be able to retrieve the value from SmallCar and LargeCar
  public int getFuelCapacity() {
    return.fuelCapacity;
  }

  public void setFuelCapacity(int fuelCapacity) {
    this.fuelCapacity = fuelCapacity;
  }

  protected int getFuelLevel() {
    return fuelLevel;
  }

  protected void setFuelLevel(int fuelLevel) {
    this.fuelLevel = fuelLevel;
  }

  // HERE goes the rest of the code

}

以下是SmallCar实施:

public class SmallCar extends AbstractCar {

  private static final int FUEL_CAPACITY = 45;

  public SmallCar() {
    // we set the value in the parent class
    super(FUEL_CAPACITY);
  }

  public int drive() {
    // HERE goes the logic for drive for SmallCar. Same method is needed
    // in the LargeCar class, because the logic differes.
  }

  // HERE goes the rest of the code

}

答案 1 :(得分:0)

如果您的容量只是Car的一个属性(仅限数据),请使用@Jernej K approach,但如果计算容量可能有一些逻辑,请使用此:

最好的方法是使用抽象方法。你把一个方法放到了抽象类

中的abstract Integer getCapacity();
public abstract class AbstractCar implements Car {

    private final RegistrationNumber registration;
    private boolean isRented;

    AbstractCar() {
        this.registration = RegistrationNumber.getInstance();
    }

    public RegistrationNumber getRegistration() {
        return registration;
    }

    public boolean isRented() {
        return isRented;
    }

    //You can use this method in other methods of AbstractCar, but is implemented in your concrete classes
    public abstract Integer getCapacity();

    public boolean isFull() {
        if (fuelLevel == getCapacity()) {
            return true;
        } else return false;
    }


}

然后在其他功能中使用它。在您的具体类中,您定义方法体:

public Integer getCapacity(){
    //Your logic to calculate capacity for every concrete class here
}

答案 2 :(得分:0)

如果您只想隐藏$( document ).ready(function() { document.getElementById('board').addEventListener("mousedown", getMouse, false); }); function getMouse(event){ console.log("Clicked canvas"); var canvas = document.getElementById('board'); var parentOffset = $(this).offset(); var relX = event.pageX - parentOffset.left; var relY = event.pageY - parentOffset.top; console.log("relX: ", relX); var b_context = canvas.getContext("2d"); b_context.beginPath(); b_context.arc(relX, relY, 5 , 0, 2 * Math.PI, true); b_context.fillStyle = "blue"; b_context.fill(); return; // get clients mouse movement for logic var cX = event.clientX + sco.canvas.offsetLeft; var cY = event.clientY + sco.canvas.offsetTop; // get the status div for returning client mouse movement and the ID of boxes var status = document.getElementById('status'); // loop through board square array for(var i = 0; i < board.square.length; i++){ // set square object to small variable var s = board.square[i]; // logic for each box boundary if(cX > s.X && cX < s.X + s.W && cY > s.Y && cY <= s.Y + s.H){ // set status div so user can see the board is interactive and not static status.innerHTML = 'clientX = '+cX+' | clientY = '+cY+' | id:'+s.id; } } } 来自类用户,而不是来自其他开发人员,则可以在 AbstractCar 中将其声明为FUEL_CAPACITY并将其初始化为子类中的适当值。另外,我会在 AbstractCar 中声明一个 getter方法 protected,它会返回此值。