Java 将对象声明为其超类和类之间的区别?
我已经阅读了java书籍的继承部分,并尝试了以下示例作为实践:Java 将对象声明为其超类和类之间的区别?,java,object,inheritance,Java,Object,Inheritance,我已经阅读了java书籍的继承部分,并尝试了以下示例作为实践: public class Car { private int wheels; private int doors; public Car(int initWheels, int initDoors){ wheels = initWheels; doors = initDoors; } public int getWheels(){ return wheels; } public int getDoors()
public class Car {
private int wheels;
private int doors;
public Car(int initWheels, int initDoors){
wheels = initWheels;
doors = initDoors;
}
public int getWheels(){
return wheels;
}
public int getDoors(){
return doors;
}
protected int calculateMaterials(){
return wheels + doors;
}
}
主要内容:
public class Main {
public static void main(String [] args){
Car car = new Car(4,4);
Car myCar = new Ford(6,2,"black", "pickup", 2);
System.out.println(myCar.getWheels());
System.out.println(myCar.calculateMaterials());
}
}
public class Main {
public static void main(String [] args){
Car car = new Car(6,2);
Car myCar = new Ford(6,2,"black", "pickup", 2);
Ford myCarToo = new Ford(6,2,"black", "pickup", 2);
System.out.println(car.calculateMaterials()); //Car.calculateMaterials
System.out.println(myCar.calculateMaterials()); //Ford.calculateMaterials
System.out.println(myCarToo.calculateMaterials()); //Ford.calculateMaterials
}
}
然而,在重新审视代码后,我开始质疑自己这是否可能:carmycar=新福特(6,2,“黑色”,“皮卡”,2)代码>。我运行了它,看到输出完全相同,现在我想知道是否:
Car myCar = new Ford(6,2,"black", "pickup", 2);
还有这个
Ford myCar = new Ford(6,2,"black", "pickup", 2);
同样的事情,如果是的话,哪一个更可取或更普遍?如果不是,我怎么会得到相同的输出?你得到相同的输出,因为汽车
是汽车
类型的参考,而不是福特
。因此,您无法将Ford
的方法传递给referencecar
,因为它的引用类型是car
而不是Ford
。因此,为了得到您想要的,您必须将参考变量car
的参考类型更改为Ford
,例如:
Ford fordCar = new Ford(6,2,"black", "pickup", 2);
但是,这个:carmycar=新车(6,2,“黑色”,“皮卡”,2)
根本不应该编译,因为Car
构造函数没有在Car
中定义的5参数构造函数。问题是,您将引用类型声明为Car
您将从
Ford myCar = new Ford(6,2,"black", "pickup", 2);
有几个人提出了一个好的观点,即您实际上并没有重载构造函数。这才是更大的问题。重载构造函数只有在顶级类和继承类的构造函数参数相同时才会真正发生。因此,根据经验法则,每当包含五个参数时,您总是调用Ford构造函数:
- 在一个方法中,使用你需要的类型(如果你需要福特特定的东西,使用福特,否则使用汽车)
- 在函数的返回值中,使用在方法中使用的相同类型
- 将值作为参数传递时,请使用参数声明中需要的类型,例如,如果只想使用特定于汽车的内容,请使用print(Car-Car),如果需要特定于福特的内容,请使用print(Ford-Ford)
哪一个更可取或更普遍
这取决于您打算如何使用引用。如果所需的方法仅适用于Car
类型的对象,则应声明引用。但是,如果您需要获取与子类相关联的详细信息(Ford
,在您的示例中),那么这就是应该声明的类型。换句话说,始终使用所需的最少特定类型
如果不是,我怎么会得到相同的输出
因为在这两种情况下,您仅使用与类型Car
关联的值。如果您不向福特添加更多特定于类型的信息,那么它可能不应该是它自己的类型。运行以下示例将打印8、10和10。对象(new)的实例化是告诉JVM要运行哪些代码,而不是类型。在本例中,myCar和MyCarto都被实例化为Ford类型,尽管它们存储在变量中,类型为Car和Ford
主要内容:
public class Main {
public static void main(String [] args){
Car car = new Car(4,4);
Car myCar = new Ford(6,2,"black", "pickup", 2);
System.out.println(myCar.getWheels());
System.out.println(myCar.calculateMaterials());
}
}
public class Main {
public static void main(String [] args){
Car car = new Car(6,2);
Car myCar = new Ford(6,2,"black", "pickup", 2);
Ford myCarToo = new Ford(6,2,"black", "pickup", 2);
System.out.println(car.calculateMaterials()); //Car.calculateMaterials
System.out.println(myCar.calculateMaterials()); //Ford.calculateMaterials
System.out.println(myCarToo.calculateMaterials()); //Ford.calculateMaterials
}
}
Car类构造函数只有2个参数,但在您的示例中,您传递了5个参数,这与Ford类匹配。这不会编译。你找到零件了吗?我同意Samhain…你绝对确定新车(6,2,“黑色”,“皮卡”,2)真的能用吗?@rec不,没有,不过我改了。键入错误。@user2895567根据您的编辑,调用myCar.calculateMaterials()的结果应该是6+2+2或10。这是不正确的。创建具有相同函数名的继承的两个类时,JVM将根据实例化的类类型调用正确的版本,而不是基于变量的类型(Car vs Ford)。@Samhain我想我编辑是为了参考您的理解。如果不是,请解释我感兴趣的原因让我们假设他实际创建了编译的代码(Card和Ford都有带5个参数的构造函数)<代码>汽车myCar=新福特(6,2,“黑色”,“皮卡”,2);myCar.calculateMaterials()
将调用Ford calculateMaterials的实现,而Car myCar=新车(6,2,“黑色”,“皮卡”,2);myCar.calculateMaterials()
将调用calculateMaterials的Car实现。@InquisitiveDiot不太可能。用户获得相同的输出,因为将调用正确的计算材料
,例如,无论变量声明为汽车
还是福特
,都将调用福特
类的计算材料
。“这才是重点。”好奇的维迪奥我不是说这样的话。您告诉它创建一个Ford
,因为您正在调用newford(…)
carfordcar=newford(6,2,“黑色”,“皮卡”,2)代码>这同样有效,但是它们有什么不同呢?@user2895567因为你不能调用fordCar
上的Ford
-特定函数,因为Ford
是一辆车,而车是一辆非福特
。