1:什么是多态
一个对象的多种状态
(老师)(员工)(儿子)
教师 a =老钟;
员工 b =老钟;
2:多态体现
父类引用变量指向了子类的对象 Father f = new Son();
父类引用也可以接受自己的子类对象
1:Father类
1:非静态成员变量x
2:静态成员变量y
3:非静态方法eat,方法体输出父类信息
4:静态方法speak();方法体输出父类信息
class Father { int x = 1; static int y = 2; void eat() { System.out.println("开吃"); } static void speak() { System.out.println("小头爸爸"); } }
2:Son类
1:非静态成员变量x
2:静态成员变量y
3:非静态方法eat,方法体输出子类信息
4:静态方法speak();方法体输出子类信息
class Son extends Father { int x = 3; static int y = 4; void eat() { System.out.println("大头儿子很能吃"); } static void speak() { System.out.println("大头儿子。"); } }
class Demo1 { public static void main(String[] args) { Father f = new Son(); // 父类引用指向了子类对象。 System.out.println(f.x); // 1 System.out.println(f.y); // 2 f.eat(); // 输出的是子类的。 f.speak(); // 输出的是父类 } }
3总结:
1:当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量
2:当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量
所以:父类和子类有相同的成员变量,多态下访问的是父类的成员变量。
3:当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法。
4:当父类和子类具有相同的静态方法(就是子类重写父类静态方法),多态下访问的是父类的静态方法。
多态前提
1:类与类之间有关系,继承或者实现
多态弊端
1:提高扩展性,但是只能使用父类引用指向父类成员。
多态特点
非静态
1:编译时期,参考引用型变量所属的类是否有调用的方法,如果有编译通过。没有编译失败
2:运行时期,参考对象所属类中是否有调用的方法。
3:总之成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点,无论编译和运行 参考左边(引用型变量所属的类)。
在多态中,静态成员函数特点,无论编译和运行都参考左边
多态练习
1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。
1:定义功能,根据输出任何图形的面积和周长。
abstract class MyShape{ public abstract double getArea(); public abstract double getLen(); }
2:定义Rect类继承MyShape
class Rect extends MyShape{ double width ; double height; Rect(){ } Rect(double width ,double height){ this.width=width; this.height=height; } public double getArea(){ return width*height; } public double getLen(){ return 2*(width+height); } }
3:定义Cricle类继承MyShape
class Circle extends MyShape{ double r; public static final double PI=3.14; Circle(){ } Circle(double r){ this.r=r; } public double getLen(){ return 2*PI*r; } public double getArea(){ return PI*r*r; } }
4:定义静态方法计算任意图形的面积和周长
1:未知内容参与运算,不能确定用户传入何种图形,使用多态。
1:形参定义为 MyShape my
2:调用计算面积方法,和计算周长方法。并打印
2:使用多态特性,子类重写了父类非静态方法,会执行子类的方法。
class Demo2{ public static void main(String[] args){ System.out.println(); print(new Rect(3,4)); //MyShape m =new Rect(3,4); print(new Circle(3)); } //根据用户传入的图形对象,计算出该图形的面积和周长 //1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。 public static void print(MyShape m){ System.out.println(m.getLen()); System.out.println(m.getArea()); } }
2:多态可以作为返回值类型。
获取任意一辆车对象
1:定义汽车类,有名字和颜色,提供有参和无参构造,有运行的行为。
class Car { String name; String color; Car() { } Car(String name, String color) { this.name = name; this.color = color; } void run() { System.out.println("跑跑。。。。"); } }
2:定义Bmw类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
class Bmw extends Car { Bmw() { } Bmw(String name, String color) { super(name, color); } void run() { System.out.println("宝马很拉风。。。。"); } }
3:定义Benz类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
class Benz extends Car { Benz() { } Benz(String name, String color) { super(name, color); } void run() { System.out.println("奔驰商务首选。。。。"); } }
4:定义Bsj类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
class Bsj extends Car { Bsj() { } Bsj(String name, String color) { super(name, color); } void run() { System.out.println("泡妞首选。。。。"); } }
5:定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
1:使用(int)Math.round(Math.random()*2); 生成0-2之间随机数。
2:使用if else 判断,指定,0,1,2 new 不同汽车 并返回。
class Demo3 { public static void main(String[] args) { int x = 0; while (x < 100) { Car c = CarFactory(); c.run(); x++; } } // 定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。 // 使用随机数,0.1.2 if 0 bsj 1 bmw 2 bc public static Car CarFactory() { int x = (int) Math.round(Math.random() * 2); if (0 == x) { return new Bmw("宝马x6", "红色"); } else if (1 == x) { return new Benz("奔驰", "黑色"); } else if (2 == x) { return new Bsj("保时捷", "棕色"); } else { return new Benz("Smart", "红色"); } } }
3:抽象类和接口都可以作为多态中的父类引用类型。 多态之类型转型
1:案例定义Father类
1:定义method1和method2方法
class Father { void method1() { System.out.println("这是父类1"); } void method2() { System.out.println("这是父类2"); } }
2:定义Son类继承Father类
1:定义method1(重写父类method1)和method2方法
class Son extends Father { void method1() { System.out.println("这是子类1"); } void method3() { System.out.println("这是子类3"); } }
3:创建Father f=new Son();
1: f.method1() 调用的子类或者父类?
2: f.method2() 编译和运行是否通过?
3: f.method3() 编译和运行是否通过?(编译报错)
class Demo4 { public static void main(String[] args) { Father f = new Son(); f.method1(); // 这是子类1 f.method2(); // 这是父类2 // f.method3(); //编译报错。 // 多态弊端,只能使用父类引用指向父类成员。 // 类类型转换 Son s = (Son) f; s.method3(); System.out.println(); } }
4:如何在多态下,使用父类引用调用子类特有方法。
1:基本类型转换:
1:自动:小->大
2:强制:大->小
2:类类型转换
前提:继承,必须有关系
1:自动:子类转父类
2:强转:父类转子类
3:类型转换
1:Son s=(Son)f
2:s.method3();
案例:
1:定义Animal类颜色成员变量,无参构造,有参构造,run方法
class Animal { String color; Animal() { } Animal(String color) { this.color = color; } void run() { System.out.println("跑跑"); } }
2:定义Dog类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Dog的特有方法ProtectHome
class Dog extends Animal { Dog() { } Dog(String color) { super(color); } void run() { System.out.println("狗儿跑跑"); } void protectHome() { System.out.println("旺旺,看家"); } }
3:定义Fish类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Fish特有方法swim
class Fish extends Animal { Fish() { } Fish(String color) { super(color); } void run() { System.out.println("鱼儿水中游"); } void swim() { System.out.println("鱼儿游泳"); } }
4:使用多态,Animal a=new Dog();
5:调用Dog的特有方法,ProtectHome
1:类类型转换,Dog d=(Dog)a;
2:d.protectHome
class Demo5 { public static void main(String[] args) { Animal ani = new Dog(); // ani.protectHome(); // 正常转换 Dog d = (Dog) ani; d.protectHome(); // 多态例外 Animal an = new Animal(); // ClassCastException // Dog d=(Dog)an // 多态例外 Animal dog = new Dog(); // ClassCastException // Fish f = (Fish) dog; } }
6:非多态
1:Animal a=new Animal();
2:类类型转换
Dog d=(Dog)a;
d.protectHome();
3:编译通过,运行出现异常
1:ClassCastException
7:多态例外
1:Animal a=new Dog();
2:类类型转换
1:Fish f=(Fish)a;
2:f.fish();
3:编译通过,运行异常
1:ClassCastException
4:虽然是多态,但是狗不能转为鱼,他们之间没有关系。
案例2
1:定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法
2:使用多态,方法形参,不能确定用户传入的是那种动物
3:使用instanceof 关键字,判断具体是何种动物,
4:类转换,执行该动物的特有方法。
class Animal { String color; Animal() { } Animal(String color) { this.color = color; } void run() { System.out.println("跑跑"); } }
class Dog extends Animal { Dog() { } Dog(String color) { super(color); } void run() { System.out.println("狗儿跑跑"); } void protectHome() { System.out.println("旺旺,看家"); } }
class Fish extends Animal { Fish() { } Fish(String color) { super(color); } void run() { System.out.println("鱼儿水中游"); } void swim() { System.out.println("鱼儿游泳"); } }
class Bird extends Animal { Bird() { } Bird(String color) { super(color); } void run() { System.out.println("鸟儿空中飞"); } void fly() { System.out.println("我是一只小小鸟。。。。"); } }
class Demo6 { public static void main(String[] args) { System.out.println(); doSomething(new Dog()); doSomething(new Bird()); doSomething(new Fish()); } // 定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法 public static void doSomething(Animal a) { if (a instanceof Dog) { Dog d = (Dog) a; d.protectHome(); } else if (a instanceof Fish) { Fish f = (Fish) a; f.swim(); } else if (a instanceof Bird) { Bird b = (Bird) a; b.fly(); } else { System.out.println("over"); } } }