多态:可以理解为事物存在的多种体现形态。
猫 x=new 猫()
动物 x=new 猫()
1,多态的体现
父类的引用指向了自己的子类对象;
父类的引用也可以接受自己的子类对象。
2,多态的前提
必须是类与类之间有关系,要么继承,要么实现;
通常还有一个前提:存在覆盖。
3,多态的好处
多态的出现大大提高了程序的扩展性。
4,多态的弊端
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5,多态的应用
///多态示例代码//
class Fu
{
static int sum=3;
public void method1()
{
System.out.println("fu_method_1");
}
public void method2()
{
System.out.println("fu_method_2");
}
public void method4()
{
System.out.println("fu_method_4");
}
public static void method5() //父类中的静态成员函数,注意父类中的静态成员函数不能够在子类中被覆盖。
{ //因为此函数是静态绑定在父类中的,谁也覆盖不了。一进内存就绑定在父类中了。静态不存在覆盖。
System.out.println("fu_method_5");
}
}
class Zi extends Fu
{
static int sum=5;
public void method1()
{
System.out.println("zi_method_1");
}
public void method3()
{
System.out.println("zi_method_3");
}
public static void method5() //子类中的静态成员函数
{
System.out.println("zi_method_5");
}
}
class DuoTaiDemo2
{
public static void main(String args[])
{
Fu f=new Zi();//父类引用指向子类对象,此为多态最明显的表现形式。
//f.method1();
//f.method2();
//f.method4();
//f.method3(); 在编译此行时出错。
System.out.println(f.sum);//result:3
//f.method5();//参考左边,左边是父类引用Fu f,则运行父类中method5
Zi z=new Zi();
System.out.println(z.sum);//result:5
//z.method5();//参考左边,左边是子类引用Zi z,则运行子类中的method5
多态中,非静态成员函数的特点:
在编译时,会查看父类引用f方调用的方法在父类中到底存不存在。显然method3在父类中并没有,而父类引用f却调用了此方法,所以编译错误。
在运行时,会查看对象所属的类中有没有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。
猫 x=new 猫()
动物 x=new 猫()
1,多态的体现
父类的引用指向了自己的子类对象;
父类的引用也可以接受自己的子类对象。
2,多态的前提
必须是类与类之间有关系,要么继承,要么实现;
通常还有一个前提:存在覆盖。
3,多态的好处
多态的出现大大提高了程序的扩展性。
4,多态的弊端
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5,多态的应用
///多态示例代码//
class Fu
{
static int sum=3;
public void method1()
{
System.out.println("fu_method_1");
}
public void method2()
{
System.out.println("fu_method_2");
}
public void method4()
{
System.out.println("fu_method_4");
}
public static void method5() //父类中的静态成员函数,注意父类中的静态成员函数不能够在子类中被覆盖。
{ //因为此函数是静态绑定在父类中的,谁也覆盖不了。一进内存就绑定在父类中了。静态不存在覆盖。
System.out.println("fu_method_5");
}
}
class Zi extends Fu
{
static int sum=5;
public void method1()
{
System.out.println("zi_method_1");
}
public void method3()
{
System.out.println("zi_method_3");
}
public static void method5() //子类中的静态成员函数
{
System.out.println("zi_method_5");
}
}
class DuoTaiDemo2
{
public static void main(String args[])
{
Fu f=new Zi();//父类引用指向子类对象,此为多态最明显的表现形式。
//f.method1();
//f.method2();
//f.method4();
//f.method3(); 在编译此行时出错。
System.out.println(f.sum);//result:3
//f.method5();//参考左边,左边是父类引用Fu f,则运行父类中method5
Zi z=new Zi();
System.out.println(z.sum);//result:5
//z.method5();//参考左边,左边是子类引用Zi z,则运行子类中的method5
多态中,非静态成员函数的特点:
在编译时,会查看父类引用f方调用的方法在父类中到底存不存在。显然method3在父类中并没有,而父类引用f却调用了此方法,所以编译错误。
在运行时,会查看对象所属的类中有没有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。
多态中,静态成员函数的特点:无论编译和运行,都参考左边。
abstract class Animal
{
public abstract void eat();
public abstract void jiao();
}
class Cat extends Animal
{
public void eat()
{
System.out.println("吃鱼");
}
public void jiao()
{
System.out.println("喵喵");
}
public void catchMouse()
{
System.out.println("捉老鼠");
}
}
class Dog extends Animal
{
public void eat()
{
System.out.println("吃骨头");
}
public void jiao()
{
System.out.println("汪汪");
}
public void kanJia()
{
System.out.println("看家");
}
}
class DoAnimal//将行为封装起来。
{
public void doSome(Animal ani)
{
ani.eat();
ani.jiao();
}
}
class DuoTaiDemo
{
public static void main(String args[])
{
//Animal an=new Cat();//类型提升,向上转型。父类引用指向子类对象,父类的引用为Animal类型。
//an.eat();
//如果想要调用猫的特有方法时,需要强制将父类的引用转成子类类型,向下转型。
//Cat ca=(Cat)an;//将父类的引用强制转换成子类类型
//ca.catchMouse();//an和ca指向的是同一只猫。
/*Cat c=new Cat();
c.eat();
Dog d=new Dog();
d.eat();*/
/*举个理解多态的例子
毕姥爷 x=new 毕老师();//毕老师装成毕姥爷去讲课
x.讲课();
毕老师 y=(毕老师)x;//毕老师卸妆成为真正的自己。
y.看电影();
发现自始至终都是毕老师一个人在扮演两个人,即多态。
*/
//function(new Cat());
//function(new Dog());
DoAnimal da=new DoAnimal();
da.doSome(new Cat());
}
public static void function(Animal a)//Animal a=new Cat();或者Animal a=new Dog();
{
a.eat();
if(a instanceof Cat)//如果a是Cat类型的。
{
Cat c=(Cat)a;
c.jiao();
c.catchMouse();
}
else if(a instanceof Dog)//如果a是Dog类型的。
{
Dog c=(Dog)a;
c.jiao();
c.kanJia();
}
}
}