多态:
Java中概念:父类类型引用指向子类对象。
概述:事物的多种状态。
- 对象的多态:同一个对象,有不同的名称和描述。
- 类的多态:同一个类,可以在不同场景下有不同的表现。
多态的前提:
- 要有子父类的继承(实现)关系。
- 有方法的重写。
- 父类的引用指向子类的对象。
(熟知)多态中成员方法的访问特点:
- 编译看左边,运行看右边。
- 编译的时候,要看【 = 】左边的引用所属的类型中,是否有该方法的定义,没有就编译失败。
- 运行的时候,要看【 = 】右边的引用所属的类型中,是如何实现该方法的。最终运行的右边子类里该方法的重写结果。
多态中的类型转换:
一,向上类型转换:子类转换成父类(由小转大)
- 语法:(直接赋值)父类 对象名 = new 子类()
class Pet{
String name;
public Pet(String name) {
this.name = name;
}
public void eat(){
//各种宠物进食不一样,不能定义
//暂时不用abstract修饰,空方法体
}
}
class Dog extends Pet{
public Dog(String name) {
super(name);
}
@Override
public void eat() {
System.out.println( name + "吃骨头");
}
}
class Cat extends Pet{
public Cat(String name) {
super(name);
}
@Override
public void eat() {
System.out.println( name + "吃鱼");
}
}
class Master{
public void feed(Pet pet){//参数是父类,调用子类在父类中继承的方法
pet.eat();
}
}
public class Demo {
public static void main(String[] args) {
//需求:主人饲养宠物
Master master = new Master();
Dog dog = new Dog("狗狗");
Cat cat = new Cat("猫猫");
master.feed(dog);//实际参数是子类
master.feed(cat);//实际参数是子类
Pet pet = new Dog("小狗");
pet.eat();
}
}
输出结果:
结论:
语法:
- 可以直接赋值 父类 对象名 = new 子类(),再调用子类继承父类中的方法,父类对象名.方法名(),输出的是子类方法重写的结果。
- 可以把父类作为其他类中方法的参数,再调用父类中被继承的方法,实例化对象,再调用方法 对象名.方法名(子类实例对象)
作用:
- 增强类的选择范围(可以访问任一继承父类的子类)
- 降低类的能力(只能访问在父类中继承的方法,无法访问自身特有的方法)
二,向下类型转换:父类转子类(由大转小)
- 语法:子类类型 引用名称 = (子类类型)父类类型的引用
class Pet{
String name;
public Pet(String name) {
this.name = name;
}
public void eat(){
//各种宠物进食不一样,不能定义
//暂时不用abstract修饰,空方法体
}
}
class Dog extends Pet{
public Dog(String name) {
super(name);
}
@Override
public void eat() {
System.out.println( name + "吃骨头");
}
public void play(){
System.out.println("玩飞盘");
}
}
class Cat extends Pet{
public Cat(String name) {
super(name);
}
@Override
public void eat() {
System.out.println( name + "吃鱼");
}
public void play(){
System.out.println("玩毛球");
}
}
class Master{
public void feed(Pet pet){//参数是父类
pet.eat();
}
public void play(Pet pet){
//instanceof关键字,判断左边的引用是否为右边类型,返回布尔值
if (pet instanceof Dog){
((Dog) pet).play();//向下转换
}
}
}
public class Demo {
public static void main(String[] args) {
Master master = new Master();
Dog dog = new Dog("狗狗");
Cat cat = new Cat("猫猫");
master.play(dog);//玩飞盘
//Pet pet = new Dog("小狗");
//pet.play();报错,向上转换只能调用继承的方法
}
}
作用:子类类型恢复原本就有的访问范围,可以访问自身特有的方法。
class Master{
public void feed(Pet pet){//参数是父类
pet.eat();
}
public void play(Pet pet){
if (pet instanceof Dog){//判断左边的引用是否为右边类型,返回布尔值
((Dog) pet).play();//向下转换
}
}
}
Master类中的play方法,父类Pet每增加一个子类,里面就要增加一个判断,多次修改代码对以后编程不利。
解决方法:工厂模式(暂没学)
多态中的属性:
- 不同名:
class Fu{
int x = 200;
}
class Zi extends Fu{
int y = 100;
}
public class Demo {
public static void main(String[] args) {
Fu fu = new Zi();
System.out.println(fu.x);//200
// System.out.println(fu.y);报错
}
}
- 同名:
class Fu{
int x = 200;
}
class Zi extends Fu{
int x = 100;
}
public class Demo {
public static void main(String[] args) {
Fu fu = new Zi();
System.out.println(fu.x);// 200
}
}
结论:
- 1、多态中访问不同名属性,编译时看表达式的左边。
- 2、多态中访问同名属性,运行时看表达式的左边。
多态中的方法:
- 不同名:
class Fu{
public void method(){
System.out.println("Fu类中的method方法.....");
}
}
class Zi extends Fu{
public void function(){
System.out.println("Zi类中的function方法.....");
}
}
public class Demo {
public static void main(String[] args) {
Fu fu = new Zi();
fu.method();//Fu类中的method方法.....
//fu.function();报错
}
}
- 同名:
class Fu{
public void method(){
System.out.println("Fu类中的method方法.....");
}
}
class Zi extends Fu{
public void method(){
System.out.println("Zi类中的method方法.....");
}
}
public class Demo {
public static void main(String[] args) {
Fu fu = new Zi();
fu.method();//Zi类中的method方法.....
}
}
- static同名方法:
class Fu{
public static void method(){
System.out.println("Fu类中的method方法.....");
}
}
class Zi extends Fu{
public static void method(){
System.out.println("Zi类中的method方法.....");
}
}
public class Demo {
public static void main(String[] args) {
Fu fu = new Zi();
fu.method();//Fu类中的method方法.....
}
}
结论:
1、多态中不同名方法,编译时看表达式的左边
2、多态中同名方法,运行时看表达式的右边
3、多态中同名静态方法,运行时看表达式的左边。
多态的内存图解