1. 但这还不是全部。
假设该类Cow
有一个printAll()
调用另外两个方法的方法。然后代码将像这样工作:
代码 |
描述 |
class Cow
{
public void printAll()
{
printColor();
printName();
}
public void printColor ()
{
System.out.println("I'm a white whale");
}
public void printName()
{
System.out.println("I'm a cow");
}
}
class Whale extends Cow
{
public void printName()
{
System.out.println("I'm a whale");
}
}
|
|
public static void main(String[] args)
{
Whale whale = new Whale ();
whale.printAll();
}
|
屏幕输出将是: I'm a white whale
I'm a whale
|
注意,在对象上调用类printAll()
中的方法时,使用的是类中的方法,而不是方法中的方法。Cow
Whale
printName
Whale
Cow
主要的不是编写方法的类,而是调用方法的对象的类型(类)。
只有非静态方法可以被继承和覆盖。静态方法不被继承,因此不能被覆盖。
这是Whale
应用继承和方法覆盖后类的样子:
class Whale
{
public void printAll()
{
printColor();
printName();
}
public void printColor()
{ System.out.println("I'm a white whale");
}
public void printName()
{
System.out.println("I'm a whale");
}
}
|
这是Whale 在应用继承和方法重写之后该类的样子: 我们不知道任何旧printName 方法。 |
2. 类型转换
这里还有更有趣的一点。因为一个类继承了其父类的所有方法和数据,所以对子类对象的引用可以存储在(分配给)类型与父类(以及父类的父类等)相同的变量中 -一直到班级Object
)。例子:
代码 |
描述 |
public static void main(String[] args)
{ Whale whale = new Whale();
whale.printColor();
}
|
屏幕输出将是: I'm a white whale
|
public static void main(String[] args)
{
Cow cow = new Whale();
cow.printColor();
}
|
屏幕输出将是: I'm a white whale
|
public static void main(String[] args)
{
Object o = new Whale();
System.out.println(o.toString());
}
|
屏幕输出将是: Whale@da435a.
方法toString() 继承自Object 类 |
这是一个非常有价值的属性:稍后您将了解如何在实践中使用它。
3. 调用对象的方法
当在变量上调用方法时,实际上是在对象上调用该方法。这种机制称为动态方法分派。
这是它的样子:
代码 |
描述 |
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printName();
}
|
屏幕输出将是: I'm a whale
|
public static void main(String[] args)
{
Cow cow = new Whale();
cow.printName();
}
|
屏幕输出将是: I'm a whale
|
printName()
请注意,被调用方法的具体实现——是类中的方法Cow
还是类中的方法Whale
——不是由变量的类型决定的,而是由变量引用的对象的类型决定的。
变量Cow
存储一个对象的引用Whale
,printName()
类中定义的方法Whale
就是被调用的。
这不是很明显。记住主要规则:
可在变量上调用的方法集由变量的类型决定。 调用的具体方法实现由变量引用的对象的类型/类决定。
你会一直遇到这个,所以你越早记住越好。
GO TO FULL VERSION