问题:
请仔细阅读下面的程序,分析程序的结构和输出结果。由此理解接口、抽象类、继承、实现接口,进一步理解多态。
interface Food
{ public void doEat();} // doEat()是吃食物的方法
abstract class Fruit{} //水果抽象类
abstract class Meat{ } //肉抽象类
class Apple extends Fruit implements Food//苹果类
{ public void doEat()
{ System.out.println("我是苹果,属于水果类,你不必烹饪我就可吃!"); }
}
class Beef extends Meat implements Food //牛肉类
{ public void doEat()
{System.out.println("我是牛肉,属于肉类,必须烹饪后才可吃!"); }
}
public class Use
{ public static void main(String args[])
{ Food f=new Apple();
f.doEat();
f=new Beef();
f.doEat(); // 两个“f.doEat()”体现了多态
}
}
试一试将主方法改为:
public static void main(String args[])
{ Food f=new Apple(); f.doEat(); }
观察系统有何反应?
再在Fruit类中加入方法“abstract void doEat();” ,看结果怎样,你能得出什么结论?
题目代码:
package com.company;
interface Food
{
public void doEat();
} // doEat()是吃食物的方法
abstract class Fruit{} //水果抽象类
abstract class Meat{} //肉抽象类
class Apple extends Fruit implements Food//苹果类
{
public void doEat()
{
System.out.println("我是苹果,属于水果类,你不必烹饪我就可吃!");
}
}
class Beef extends Meat implements Food //牛肉类
{
public void doEat()
{
System.out.println("我是牛肉,属于肉类,必须烹饪后才可吃!");
}
}
public class Main {
public static void main(String[] args) {
Food f=new Apple();
f.doEat();
f=new Beef();
f.doEat(); // 两个“f.doEat()”体现了多态
}
}
题目代码运行结果:
将主方法修改为:
public class Main {
public static void main(String[] args) {
Food f=new Apple();
f.doEat();
}
}
运行结果:
接口可以作为一种引用类型来使用。任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类所实现的接口中的方法。Java运行时系统动态地确定该使用哪个类中的方法。
把接口作为一种数据类型可以不需要了解对象所对应的具体的类,而着重于它的交互界面。例如,当Person类实现了Runner接口,可以如下赋值,和子类对象赋给父类对象是类似的:
Runner r=new Person();
父类对象与子类对象的转换:
(1)子类对象转为父类对象时,可以是显示的或隐式的,子类对象直接向父类对象赋值;
(2)父类对象不能被任意地转换成某一子类的对象,只有父类对象指向的实际是一个子类对象,那么这个父类对象可以转换成子类对象,但此时必须用强制类型转换;
(3)如果一个方法的形式参数定义的是父类对象,那么调用这个方法时,可以使用子类对象作为实际参数。
将Fruit类修改为
abstract class Fruit
{
abstract void doEat();
} //水果抽象类
运行结果:
Apple类中实现了接口Food中的doEat()方法(接口优先于抽象类,故实现的是接口Food的doEat()方法,而非抽象类Fruit的doEat()),所以当程序运行时接口Food作为一种数据类型,得到Apple类对象的赋值后,实现Apple类的doEat()方法。因此,运行结果为“我是苹果,属于水果类,你不必烹饪我就可吃!”