我想问一下我遇到的问题。 假设我们有一个名为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,并在同一个类中按需使用它们,而不必重写所有这些。
谢谢!
答案 0 :(得分:1)
您可以在子类(override
)中Car
超类(Car2
)的方法,这称为多态,这是OOP的核心原则之一。这个原则允许我们根据在运行时传递的实际对象(Car
或Car2
对象)来调用不同的类行为。
对于您的问题,您可以按照状态模式提供动态行为,具体取决于传递的类型和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)
如果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
实施界面如果实现完全不同,Car
和Car2
应该从BaseCar
/ ICar
继承。