说明:记住多态下只有非静态成员方法是编译依据父类,运行依据子类的。
一,多态
多态的前提是继承或者实现。此时子类的对象可以指向本类类型引用,也可以子向父类类型引用。
当父类引用指向子类对象时称为多态。
class Fu{
void show(){
System.out.println("父类方法");
}
}
class Zi extends Fu{
void show(){
System.out.println("子类方法");
}
}
public class Test {
public static void main(String[] args){
//父类引用指向子类对象,称为多态
Fu f=new Zi();
//子类引用指向本类对象
Zi z=new Zi();
}
}
二,多态中成员方法的调用
多态时,可以调用父类方法,也可以调用子类方法,当调用子类方法时,该方法必须时覆盖父类的方法,否则调用失败。
class Fu{
void show(){
System.out.println("父类方法show");
}
}
class Zi extends Fu{
void print(){
System.out.println("子类方法print");
}
}
public class Test {
public static void main(String[] args){
//父类引用指向子类对象,称为多态
Fu f=new Zi();
//调用父类方法
f.show();
//调用子类方法,调用失败,因为父类中没有该方法,不是重写方法
f.print();
}
}
当子类覆盖了父类中某方法时,多态情况下,调用该方法,运行的是子类方法。
class Fu{
void print(){
System.out.println("父类方法");
}
}
class Zi extends Fu{
void print(){
System.out.println("子类方法");
}
}
public class Test {
public static void main(String[] args){
//父类引用指向子类对象,称为多态
Fu f=new Zi();
//运行的是子类方法
f.print();
}
}
运行结果
子类方法
三,多态下其他成员的调用
在多态情况下,除了非静态方法以外的其他成员被调用时,运行的都是父类中的成员。
1.成员变量
class Fu{
int x=4;
}
class Zi extends Fu{
int x=7;
}
public class Test {
public static void main(String[] args){
Fu f=new Zi();
//运行的是父类的成员变量
System.out.println(f.x);
}
}
运行结果
7
2.静态方法
class Fu{
static void show(){
System.out.println("父类静态方法");
}
}
class Zi extends Fu{
static void show(){
System.out.println("子类静态方法");
}
}
public class Test {
public static void main(String[] args){
Fu f=new Zi();
//运行的是父类的静态方法
f.show();
}
}
运行结果:
父类静态方法
四,转型。
将子类对象指向父类引用称为向上转型;
将父类引用转换为子类类型称为向下转型;
class Fu{
void show(){
System.out.println("父类方法");
}
}
class Zi extends Fu{
void show(){
System.out.println("子类方法");
}
}
public class Test {
public static void main(String[] args){
//向上转型
Fu f=new Zi();
//向下转型
Zi z=(Zi)f;
}
}
注:转型的前提是子类对象,当对象为父类对象时,不能转型:
class Fu{
void show(){
System.out.println("父类方法");
}
}
class Zi extends Fu{
void show(){
System.out.println("子类方法");
}
}
public class Test {
public static void main(String[] args){
//父类对象
Fu f=new Fu();
//异常:不能将父类对象转换为子类类型
Zi z=(Zi)f;
}
}
五,多态的运用
多态通常运用于,一个继承体系中的父类引用做为函数的形式参数,这样这个函数就可以传入这个继承体系中的子类对象做为实际参数进行运算。
//动物类
abstract class Animal{
//抽象方法
abstract void eat();
}
//定义动物类的子类
class Cat extends Animal{
//复写父类中抽象方法
void eat(){
System.out.println("猫吃鱼");
}
}
//定义动物类的子类
class Dog extends Animal{
//复写父类中的抽象方法
void eat(){
System.out.println("狗吃肉");
}
}
public class Test {
public static void main(String[] args){
//子类对象做为函数的实际参数
show(new Cat());
//子类对象做为函数的实际参数
show(new Dog());
}
//将父类引用做为形式参数
public static void show(Animal a){
//调用方法,运行的是子类中的方法
a.eat();
}
}
运行结果;
猫吃鱼
狗吃肉