多态
某一个事物,在不同时刻表现出来的不同状态。
举例:
--| 猫可以是猫的类型。 猫 m = new 猫();
--| 同时猫可以是动物类型,也可以把猫称为动物。 动物 d = new 猫();
猫这类事物即具备猫的形态,又具备着动物的形态。
class 动物 //父类
{
}
class 猫 extends 动物 //子类
{
}
class 狗 extends 动物
{
}
猫 x = new 猫;
动物 x = new 猫; //父类指向子对象,体现出多态性
多态的前提:
1/多态要有继承关系
2/必须要有重写(不重写就没意义)
3/ 要有父类引用指向子类对象。(父类 f = new 子类();)
范例:
class Fu
{
public void show()
{
System.out.println("show Fu");
}
}
class Zi extends Fu //前提①:zi类继承父类
{
public void show() //前提②:对父类方法重写
{
System.out.println("show Zi");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
Fu f = new Zi(); //前提③:父类引用指向子类对象
}
}
多态中的成员访问特点:
1 / 成员变量
编译看左边,运行看左边。(变量看的父类的)
2 / 构造方法
创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
3 / 成员方法
编译看左边,运行看右边。(因为方法重写,父类方法被子类覆盖,只留下子类方法)
4 / 静态方法
编译看左边,运行看左边。(静态方法算不上重写,静态和类相关,所以访问的还是左边)
由于成员方法存在方法重写,所以运行看右边。
多态的好处:
1 / 提高了代码的维护性(用继承保证)
2 / 提高了代码的扩展性,前期定义的代码可以使用后期的内容。(由多态保证)
范例:
/*
通过动物来示范多态的扩展性
*/
class Animal //定义一个Animal父类
{
public void eat()
{
System.out.println("eat");
}
public void sleep()
{
System.out.println("sleep");
}
}
class Cat extends Animal //定义一个cat类继承Anamal类
{
public void eat() //重写父类方法
{
System.out.println("小猫吃鱼");
}
public void sleep() //重写父类方法
{
System.out.println("小猫趴着睡觉");
}
}
class Dog extends Animal //定义一个Dog类继承Anamal类
{
public void eat() //重写父类方法
{
System.out.println("小狗啃骨头");
}
public void sleep() //重写父类方法
{
System.out.println("小狗站着睡觉");
}
}
/*
可以不断定义新的动物,继承父类Animal的共性,提高了扩展性
*/
class AnimalTool //定义一个Animal工具类,调用对象方法
{
private AnimalTool() //定义一个私有空参构造方法
{
}
public static void useAnimal(Animal a) //定义一个静态Animal带Animal参数的方法
{
a.eat();
a.sleep();
}
}
class DuoTaiDemo_02
{
public static void main(String[] args)
{
Animal c1 = new Cat(); //用父类引用指向子类对象,定义cat对象
Animal c2 = new Cat();
Animal c3 = new Cat();
AnimalTool.useAnimal(c1); //用(类名.方法名)传参,调用工具类方法
AnimalTool.useAnimal(c2);
AnimalTool.useAnimal(c3);
System.out.println("---------------------------------");
Animal d1 = new Dog();
Animal d2 = new Dog();
Animal d3 = new Dog();
AnimalTool.useAnimal(d1);
AnimalTool.useAnimal(d2);
AnimalTool.useAnimal(d3);
}
}
多态的弊端(局限性):
不能使用子类的特有功能。
需要用到子类特有功能时可以用的方法:
a / 创建子类对象,调用子类方法。(但是不合理,实际是创建了两个对象:Fu f = new Zi(); Zi z = new Zi();)
b / 把父类的引用强制转换为子类引用。 (Zi z = (Zi) f;)
对象间转型:
向上转型:Fu f = new Zi();
**向上转型的作用是限制对对象特有功能的访问。
向下转型:Zi z = (Zi)f;
**向下转型的目的是为了使用子类中的特有方法。
范例:
class DuoTime02
{
public static void main(String[] args)
{
Animal a = new Cat(); //自动类型提升。Cat对象提升为Animal类型。访问上出现局限性,不能访问Cat的特有功能。作用就是限制对特有功能的访问。
//向上转型。
a.eat();
//如果还想使用具体Cat的特有功能。可以将该对象进行向下转型。
Cat c = (Cat)a; //向下转型的目的是为了使用子类中的特有方法。
c.eat();
c.catchMouse();
}
public static void method(Animal a) //Animal a 在不断指向Animal的子类对象,体现了子类对象的多态性 (Animal a = new Dog(); Animal a = new Cat();)
{
a.eat();
}
}
abstract class Animal //定义一个抽象父类
{
abstract void eat(); //抽取相同的不具体的函数
}
class Dog extends Animal //定义一个子类,继承了父类
{
void eat()
{
System.out.println("啃骨头"); //对父类方法进行覆盖
}
void lookHome()
{
System.out.println("看家"); //子类特有函数
}
}
class Cat extends Animal
{
void eat()
{
System.out.println("吃鱼");
}
void catchMouse()
{
System.out.println("抓老鼠");
}
}
练习01:南北方人饮食案例
/*
南北方人案例
*/
class Person
{
private void Person()
{
}
public void eat()
{
System.out.println("eat");
}
}
class SouthPerson extends Person
{
void SouthPerson()
{
}
public void eat()
{
System.out.println("南方人吃米饭");
}
public void sell()
{
System.out.println("南方人经商");
}
}
class NorthPerson extends Person //定义北方人类,继承Perfon
{
void NorthPerson()
{
}
public void eat()
{
System.out.println("北方人吃面食");
}
public void work() //定义北方人特有方法
{
System.out.println("北方人实业");
}
}
class DuoTaiTest_01
{
public static void main(String[] args)
{
Person p1 = new SouthPerson(); //多态,继承父类方法
p1.eat();
SouthPerson p11 = (SouthPerson)p1; //向下强转,调用子类特有方法
p11.sell();
System.out.println("---------------");
Person p2 = new NorthPerson();
p2.eat();
NorthPerson p22 = (NorthPerson)p2;
p22.work();
}
}
类型判断 关键字 intanceof(通常在向下转型前用于代码健壮性的判断)
instanceof 用于判断对象的具体类型,只能用于医用数据类型判断。
示例: if ( a instanceof Cat)