将新属性添加到现有对象

时间:2016-11-06 11:29:15

标签: java object inheritance attributes

我想问一下我遇到的问题。 假设我们有一个名为Vehicle的接口。

然后我们有一个实现这个名为Car的接口的类。 然后另一个叫做自行车。

现在整个代码使用这两个对象(Car,Bicycle)和需要的界面Vehicle。

如果现在我想向Car类添加一个新属性,并且由于此更改,还会修改其某些方法。例如,我可以使用名为Car2的类扩展Car。但是现在如果我想在代码中使用Car2,我将不得不重写使用Car的每个方法和类到一个将使用Car2的新类。

例如,不属于Car class的方法。

int checkSpeed(Car c) {
    speed = c.attributeX * 100
}

现在我希望这种方法能够接受Car2并改变计算速度的方式。我是否需要重写类和方法,或者有更简单的方法吗?

请记住,我不想完全修改Car,我只想拥有Car和Car2,并在同一个类中按需使用它们,而不必重写所有这些。

谢谢!

6 个答案:

答案 0 :(得分:1)

您可以在子类(override)中Car超类(Car2)的方法,这称为多态,这是OOP的核心原则之一。这个原则允许我们根据在运行时传递的实际对象(CarCar2对象)来调用不同的类行为。

对于您的问题,您可以按照状态模式提供动态行为,具体取决于传递的类型和checkSpeed()的实际实现,如下所示:

SpeedChecker课程:

public class SpeedChecker {
  int checkSpeed(Vehicle v) {
    //depending upon the Vehicle type object passed, checkSpeed() will be called
    v.checkSpeed();
 }
}

汽车类:

public Car implements Vehicle {
    int checkSpeed(Car c) {
       //Add specific logic for Car
    }
} 

Car2课程:

public Car2 implements Vehicle {
    int checkSpeed(Car c) {
       //Add specific logic for Car2
    }
} 

答案 1 :(得分:0)

您可以检查对象Car c是否实际上属于Car2类型:

int checkSpeed(Car c) {
    if(c instanceof Car2){
        //do something if c is actually Car2, such as  
                   use attributes that exist in Car2 but not in Car
    else{
        //the regular case
        speed = c.attributeX * 100
    }
}

答案 2 :(得分:0)

  

请记住,我不想完全修改Car,我只想拥有Car和Car2,并在同一个类中按需使用它们,而不必重写所有这些。

由于您的示例方法违反了OOP中最重要的原则:信息隐藏,因此您的设计已经破损。拒绝解决这个问题,因为这需要做很多工作 会导致更多的工作,就像现在这样做。这项额外的工作将呈指数级增长并损害你的最后期限......

  

例如,不属于Car class的方法。

int checkSpeed(Car c) {
    speed = c.attributeX * 100
}

让我们忘记这一点甚至不能编译......

  

现在我希望这种方法能够接受Car2并改变计算速度的方式。我是否需要重写类和方法,或者有更简单的方法吗?

如果此方法是Vehicle界面的一部分并在Car(和Bicycle)中实现,您可以在Car2中以任何方式实现它。不改变程序中的任何其他内容。

这就是OOP的全部意义所在。但只有你知道并遵循其原则才能获得这种优势......

答案 3 :(得分:0)

正如Sami Kuhmonen所说:

  

如果Car2继承自Car,那么它就是Car本身

我会详细说明。你说:

  

现在我希望这种方法能够接受Car2并改变它   它计算速度的方式。我需要重写类和方法吗?   或者有更简单的方法吗?

如果你不添加方法但是修改它们的内容,你应该通过接口编程或通过合适的共同祖先组件编程更一般地推理。 在Java中,如果基类或接口更合适,多态性允许在声明它时不特定地键入实例。

这里:

int checkSpeed(Car c) {
    speed = c.attributeX * 100
}

你可以作为参数发送一个Car或它的任何子类,有一个Car2 因此,在适当的情况下,您应该将Car基类保持为声明的类型,尤其是在可能采用其中一种或另一种类型的方法中。

它会起作用:

Car myCar = new Car();
checkSpeed(myCar);
Car2 myCar2 = new Car2();
checkSpeed(myCar2);
...
int checkSpeed(Car c) {
    speed = c.attributeX * 100
}

它不会编译:

Car myCar = new Car();
checkSpeed(myCar);
Car2 myCar2 = new Car2();
checkSpeed(myCar2);
...
int checkSpeed(Car2 c) {
    speed = c.attributeX * 100
}

答案 4 :(得分:0)

在这种情况下,

lelearer方法将让Vehicle对象本身确定如何计算速度。这是有道理的,因为所需的所有信息都已经封装在Vehicle类中。

我的意思是有这样的界面:

pulbic interface Vehicle {
     int getSpeed();
}

接口的实现。对于Car

public class Car implements Vehicle {
// some car stuff
...
    @Override
    public int getSpeed() {
        return carspeed;
    }
...
}

对于Car2

public class Car2 implements Vehicle {
// some car2 stuff
...
    @Override
    public int getSpeed() {
        return car2speed;
    }
...
}

现在你的检查方法看起来像这样:

public int checkSpeed(Vehicle v) {
    int speed = v.getSpeed();
    // do the checks
    ...
    return someResult;
}

通过这种方式,您无需了解车辆本身的类型即可检查其速度。这是多态性的全部要点。

如果您无法修改现有接口,我建议您使用包含所有必需方法的Vehicle扩展原始SpeedVehicle接口,并基于它构建类层次结构。

答案 5 :(得分:0)

如果Car2始终是Car并且需要Car的所有行为,那么您需要Car2继承Car。如果Car2并非总是Car,但它们有共同点,那么您需要确定共同点,将其作为BaseCar类或ICar实施界面如果实现完全不同,CarCar2应该从BaseCar / ICar继承。