java 多态polymorphic

多态polymorphic

引出多态的问题

在这里插入图片描述

由于使用传统方法带来的问题是:代码的复用性不高,而且不利于代码维护

解决方案:使用多态解决

多态基本介绍和具体体现

基本介绍:方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

多态的具体体现(记住)

1.方法的多态

重写和重载就是体现多态

重载多态:通过不同的参数个数去调用sum方法,就会去调用不同方法,因为对sum方法来说,就是多种状态的体现

重写多态:根据对象不一样,我们调用的方法不一样

2.对象的多态(核心)

  1. 一个对象的编译类型和运行类型可以不一致
  2. 编译类型在定义对象时,就确定了,不能改变
  3. 运行类型是可以变化的
  4. 编译类型看定义时 = 号的左边 运行类型看 = 号的右边
Animal animal = new Dog();【animal编译类型是Animal,运行类型是Dog,就是animal是固定的不能改变】
animal = new Cat();【animal的运行类型变成了Cat,编译类型仍然是Animal不能改变,运行类型是指animal开始指向Dog对象,后来指向了Cat对象】

package JAVA面向对象中级部分.encapsulationAndInherit.polymorphic_.obectpoly;

public class Animal {
    public void cry(){
        System.out.println("Animal中的cay() 动物在叫。。。");
    }
}

package JAVA面向对象中级部分.encapsulationAndInherit.polymorphic_.obectpoly;

public class Cat extends Animal{
    public void cry(){
        System.out.println("Cat 小猫喵喵叫。。。");
    }
}

package JAVA面向对象中级部分.encapsulationAndInherit.polymorphic_.obectpoly;

public class Dog extends Animal{
    public void cry(){
        System.out.println("Dog 小狗汪汪叫。。。");
    }
}

package JAVA面向对象中级部分.encapsulationAndInherit.polymorphic_.obectpoly;

public class Poly01 {
    public static void main(String[] args) {
        //体验对象多态特点
        //animal编译类型是Animal,运行类型是Dog
        Animal animal = new Dog();//animal指向Dog对象
        //因为运行时,执行到这行时,animal的运行类型是Dog,所以cry就是Dog的cry中的方法
        animal.cry();//小狗汪汪叫

        //animal编译类型是Animal运行类型就是Cat
        animal = new Cat();//animal指向Cat对象
        animal.cry();//小猫喵喵叫
    }
}

多态注意事项和细节(记住)

多态的前提是:两个对象(类)存在继承关系

多态的向上转型

本质:父类的引用指向子类的对象

语法:父类类型 引用名 = new 子类类型();

特点(记住)

  1. 编译类型看左边,运行类型看右边
  2. 可以调用父类中的所有成员(成员方法和属性并且需要遵守访问权限),不能调用子类中特有成员
  3. 最终运行效果看子类的具体实现

注意是:编译和运行是两个不同的阶段,两者所遵守的规则有差异,编译阶段父类的引用不能调用子类特有的方法和属性,运行阶段调用却从子类向上查找调用(遵守就近原则)(记住规则)

多态的向下转型

语法:子类类型 引用名 = (子类类型)父类引用;

特点(记住)

  1. 只能强转父类的引用,不能强转父类的对象
  2. 要求父类的引用必须指向的是当前目标类型的对象(意思就是父类的引用当前是指向Cat,强转时也必须只能强转成Cat,不能强转别的类否则报错)
  3. 当向下转型后,可以调用子类类型中所有的成员
package JAVA面向对象中级部分.encapsulationAndInherit.detail_;

public class PolyDetail {
    public static void main(String[] args) {
        //向上转型:父类的引用指向了子类的对象
        //语法:父类类型  引用名 = new 子类类型();
        Animal animal = new Cat();
        //Object object = new Cat();//可以Object也是Cat的父类

        /**
         * 向上转型调用方法的规则如下:
         * 1.可以调用父类中的所有成员(需要遵守访问权限)
         * 2.但是不能调用子类的特有的成员:因为在编译阶段,能调用哪些成员(成员方法和属性),是由编译类型来决定的
         * 3.最终运行效果看子类(运行类型)的具体实现,即调用方法时,按照从子类(运行类型)开始查找方法,规则就是就近规则
         */
        animal.eat();//输出猫吃鱼是因为Cat中有此方法
        animal.run();
        animal.show();
        animal.sleep();

        //多态的向下转型
        //1.语法:子类类型  引用名 = (子类类型)父类引用;
        //问一个问题?cat的编译类型,运行类型是cat
        Cat cat = (Cat) animal;
        cat.catchMouse();//猫抓老鼠
        //2.要求父类的引用必须指向的是当前目标类型的对象
    }
}

package JAVA面向对象中级部分.encapsulationAndInherit.detail_;

public class Animal {
    String name = "动物";
    int age = 10;
    public void sleep(){
        System.out.println("动物睡觉");
    }
    public void run(){
        System.out.println("动物在跑");
    }
    public void eat(){
        System.out.println("动物在吃");
    }
    public void show(){
        System.out.println("hello 您好");
    }
}

package JAVA面向对象中级部分.encapsulationAndInherit.detail_;

public class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }

    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}

细节3:在多态中属性没有重写之说,属性的值看编译类型(也就是编译看左边运行看左边),静态方法和属性一样(编译看左边运行看左边)(记住)

细节4:instanceOf比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型(记住)

package JAVA面向对象中级部分.encapsulationAndInherit.detail_;

public class VerPoly {
    public static void main(String[] args) {
        //**细节3:在多态中属性没有重写之说,属性的值看编译类型(也就是编译看左边运行看右边)
        // ,静态方法和属性一样(编译看左边运行看右边)**(记住)
        Father father = new Father();
        //属性的值编译看左边,运行看左边和静态方法一样
        System.out.println(father.n1);//100
        Son son = new Son();
        //注意说明:属性没有重写之说
        System.out.println(son.n1);//200

        //**细节4:``instanceOf``比较操作符,
        // 用于判断对象的运行类型是否为XX类型或XX类型的子类型**(记住)
        System.out.println(father instanceof  Object);//true
        System.out.println(father instanceof Father);
        System.out.println(son instanceof  Father);
        //说明是XX类型本身或者是XX类型的子类类型就可以,否则编译通不过,报错
    }
}
class Father {
    int n1 = 100;
}

class Son extends Father {
    int n1 = 200;
}

练习:必须完成下面两题

在这里插入图片描述

在这里插入图片描述

案例2class Base{
	int count = 10;
	public void display(){
		System.out.println(this.count)
	}
}

class Sub extends Base{
	int count = 20;
	public void display(){
		System.out.println(this.count)
	}
}

Public class PolyExercise02{
	public static void main(String[] args){
		Sub s = new Sub();
		System.out.println(s.count);//20
		s.display();//20
		System.out.println(b==s);//true,两者都是指向SOn对象
		System.out.println(b.count);//10
		b.display();//20
	}
}

一定要理解编译和运行两个阶段,编译是看左边,并且不能使用子类特有的方法,运行看右边,从子类开始向上查找(就近原则)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值