1.多态的概述
多态概述:在同一时刻体现出事物的不同状态 (如:水(气态、固态、液态))
在面向对象Java语言中、多态的前提条件:
1)必须有继承关系,如果没有继承关系,无意义
2)必须有方法重写,在继承关系中,父类比较抽象(动物类),
动物类
eat(){...}
子类:
狗类,
eat("狗吃骨头!!"){}
猫类
eat("猫吃鱼!!"){}
3)必须父类引用指向子类对象(向上转型) ;
格式:
父类名 对象名 = new 子类名() ;
2.在多态中的成员访问特点:
成员变量:编译看左边,运行看左边
构造方法:在多态中,父类对象的创建时通过new 子类名(),优先让父类进行数据初始化
成员方法(非静态):编译看左边,运行看右边
静态的成员方法:(静态成员方法算不上方法重写,因为静态跟类有关系)编译看左边,运行看左边
以后的成员方法,指的都是非静态(如果子类出现和父类一样的方法声明,存在方法重写) 在多态中成员方法 编译看左,运行看右
//动物类
class Animal{
public int num = 10 ;
public void method(){
System.out.println("method Animal...") ;
}
public static void function(){
System.out.println("function Animal...");
}
}
//猫类
class Cat extends Animal{//继承关系
public int num = 50 ;
public int num2 = 20 ;
public void method(){
System.out.println("method Cat...") ;
}
public static void function(){
System.out.println("function Cat...");
}
}
//狗类
class Dog extends Animal{
}
//测试类
class DuoTaiDemo{
public static void main(String[] args){
//3)父类引用指向子类对象
//父类名 对象名 = new 子类名() ;
Animal a = new Cat() ;
System.out.println(a.num) ; //10
//System.out.println(a.num2) ; //编译报错,找不到符号
a.method() ;
a.function() ;
}
}
3.使用多态的好处
1、提高了程序的维护性(由继承关系保证)
2、提高了代码的扩展性(由多态的保证)
//定义一个动物类
class Animal{
public void eat(){
System.out.println("吃") ;
}
public void sleep(){
System.out.println("睡觉") ;
}
}
//狗类
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头...") ;
}
public void sleep(){
System.out.println("狗躺着睡觉...") ;
}
}
//猫类
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼...") ;
}
public void sleep(){
System.out.println("猫趴着睡觉...") ;
}
}
//猪类
class Pig{
public void eat(){
System.out.println("猪吃白菜...") ;
}
public void sleep(){
System.out.println("猪卧着睡觉...") ;
}
}
//为了方便访问,如果一直使用方法改进,太麻烦,可以提供一个类AnimalTool:针对动物操作的工具类
class AnimalTool{
private AnimalTool(){} //私有无参构造,为了让外界不能直接创建对象
//针对狗类操作的
/*
public static void useDog(Dog d){
d.eat() ;
d.sleep() ;
}
//针对猫类操作的
public static void useCat(Cat c){
c.eat();
c.sleep() ;
}
public static void usePig(Pig p){
p.eat() ;
p.sleep() ;
}
*/
//针对上述中操作,想办法提供所有的动物操作
public static void useAnimal(Animal a){//需要的该类对象的地址值引用!
a.eat() ;
a.sleep() ;
}
}
//测试类
class DuoTaiDemo2{
public static void main(String[] args){
//我养了一只狗
Dog d1 = new Dog() ;
d1.eat() ;
d1.sleep() ;
System.out.println("--------------") ;
//我很喜欢狗,又养了一只
Dog d2 = new Dog() ;
d2.eat() ;
d2.sleep() ;
System.out.println("--------------") ;
Dog d3 = new Dog() ;
d3.eat() ;
d3.sleep();
System.out.println("--------------------") ;
//改进之之后
//useDog(d1) ;
//useDog(d2) ;
//useDog(d3) ;
System.out.println("--------------------") ;
Cat c1 = new Cat();
Cat c2 = new Cat() ;
Cat c3 = new Cat() ;
//useCat(c1) ;
//useCat(c2) ;
//useCat(c3) ;
System.out.println("--------------------") ;
//第二次改进调用 ,
//AnimalTool.useDog(d1) ;
//AnimalTool.useDog(d2) ;
//AnimalTool.useDog(d3) ;
//这种方式可以,但是呢,随便去改变工具类中的代码,后期维护太麻烦了...
//第三次改进之后调用
AnimalTool.useAnimal(d1) ; //多态的形式Animal a = new Dog() ;/new Cat() /new Pig()
AnimalTool.useAnimal(c1) ; //多态的形式Animal a = new Dog() ;/new Cat() /new Pig()
Pig p1 = new Pig() ;
AnimailTool.useAnimal(p1) ; //Animal a = new Pig() ;
}
//
//对象不断在创建,调用的时候对象名不一样,方法没有变化,将eat(),sleep功能封装方法
/*
public static void useDog(Dog d){
d.eat() ;
d.sleep() ;
}
public static void useCat(Cat c){
c.eat();
c.sleep() ;
}
*/
//添加方法
}
4.多态中的弊端
多态中无法直接访问子类的特有功能!!
解决:
多态的第三个前提条件:
父类引用指向子类对象 Fu fu = new Zi() ; 向上转型
在多态中,如果能够去使用子类本身的引用,就能够访问子类的特有功能?
1)子类new子类对象
Zi zi = new Zi() ;
zi.playGame() ;
虽然可以,但是从内存角度考虑,比较消耗内存空间
2)将父类引用强制转换为子类对象 (向下转型)
Zi zi = (Zi)fu;
class Fu{
public void method(){
System.out.println("method fu...") ;
}
public void function(){
System.out.println("function fu...") ;
}
}
class Zi extends Fu{
public void method(){
System.out.println("method Zi...") ;
}
public void playGame(){
System.out.println("会玩王者农药...") ;
}
}
//测试
class DuoTaiDemo3{
public static void main(String[] args){
//父类引用指向子类对象
Fu fu = new Zi() ;
fu.method() ;//method Zi...
fu.function() ;
//fu.playGame() ;//找不到符号
System.out.println("----------------") ;
//Zi zi = new Zi() ;
//zi.playGame() ;
//将父类引用强制转换为子类对象 (向下转型) ,前提必须存在fu的引用
//向下转型:使用不当,经常会出现一次,ClassCastException:类转换异常 (看内存中是谁)
Zi zi = (Zi)fu;
zi.playGame() ;
}
}