美文网首页Java进阶之路读书Java
Java入门姿势 三大特性之一多态性

Java入门姿势 三大特性之一多态性

作者: java搬砖从来不加班 | 来源:发表于2021-09-14 13:28 被阅读0次

    多态(polymorphism)是面向对象三大特征之一。同一行为,通过不同的子类,可以体现出来的不同的形态。

    多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。 比如:同样是调用人的“休息”方法,张三是睡觉,李四是旅游,王五是听音乐; 同样是调用人“吃饭”的方法,中国人用筷子吃饭,英国人用刀叉吃饭,印度人用手吃饭。

    编译器类型指的是‘=’左边的类型,运行期类型指的是‘=’右边的类型。当有继承关系时,可能发生编译期类型和运行期类型不同的情况,即编译期类型是父类类型,运行期类型是子类类型。即:父类引用指向子类对象

    多态的要点:

    多态是方法的多态,不是属性的多态(多态与属性无关)。

    多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。

    父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。

    编写代码,为多态做准备:

    public class Programmer {
        public String name ="proName";//姓名
        //1.子类继承的
        public void writeCode(){
            System.out.println("writing code............");
        }
        //2.子类重写的
        public void eat(){
            System.out.println("eating with mouse.............");
        }
    }
    public class Chinese extends  Programmer{
        public String name = "ChinName";
        //1.从父类继承一个方法 writeCode()
        //2.重写父类的一个方法 eat
        public void eat() {
            System.out.println(" Chinese eat rice with chopsticks.....");
        }
        //3.子类特有的方法
        public void playShadowBoxing(){
            System.out.println("Chinese play showdowBoxing every day......");
        }
    }
    public class English extends Programmer {
        //1.从父类继承一个方法 writeCode()
        //2.重写父类的一个方法 eat
        public void eat() {
            System.out.println("English eating meat with knife.....");
        }
        //3.子类特有的方法
        public void raceHorse(){
            System.out.println("English like racing horse......");
        }
    }
    public class Italian extends  Programmer {
        //1.从父类继承一个方法 writeCode()
        //2.重写父类的一个方法 eat
        public void eat() {
            System.out.println("Italian eating pizza with hand......");
        }
        //3.子类特有的方法
        public void playFootBall(){
            System.out.println("Italian like play football.....");
        }
    }
    

    实现eat()多态

    public class Test {
    //    public static  void showEat(Chinese ch){
    //        ch.eat();
    //    }
    //    public static void showEat(Italian it){
    //        it.eat();
    //    }
    //    public static void showEat(English en){
    //      en.eat();
    //    }
        public static void showEat(Programmer pro){
            pro.eat();
        }
    public static void main(String[] args) {
            //Chinese ch = new Chinese();
            Programmer ch = new Chinese();
            showEat(ch);
            English en = new English();
            showEat(en);
            Italian it = new Italian();
            showEat(it);
            Programmer pro = new Programmer();
            showEat(pro);
        }
    }
    public class Test2 {
        public static void main(String[] args) {
            Chinese ch = new Chinese();
            ch.writeCode();//从父类继承的
            ch.eat();//重写父类的
            ch.playShadowBoxing();//子类特有的方法
            Programmer ch2 = new Chinese();
            ch2.writeCode(); //非多态
            ch2.eat(); //  多态  调用的是子类重写的方法
            //ch2.playShadowBoxing(); // 无法调用子类特有的方法
        }
    }
    

    使用父类做方法的形参,是多态使用最多的场合。即使增加了新的子类,方法也无需改变,符合开闭原则。

    父类引用做方法的形参,实参可以是任意的子类对象,可以通过不同的子类对象实现不同的行为方式。另外即使增加了新的子类,方法也无需改变,提高了扩展性,符合开闭原则。

    多态之向上转型

    将子类对象赋给父类引用,称为向上转型(upcasting),自动进行类型转换。

    向上转型可以调用的子类继承的方法,但不能调用子类特有的方法。需要特别理解的是如果子类重写了父类的方法,向上转型后通过父类引用调用的却是真实子类重写的方法,

    向上转型-代码示例:

    public class TestPoly {
        public static void main(String[] args) {
            //基本数据类型的自动转换
            int n = 10;
            System.out.println( n );
            double d = n;  // 左>右  自动转换
            System.out.println(d);
            //引用数据类型的自动转换
            Programmer programmer = new Chinese(); // 自动转换  向上转型  左>右
            programmer.writeCode();
            programmer.eat();
            //programmer.playShadowBoxing();
        }
    }
    

    如何理解向上转型?

    招聘程序员,来个英国籍程序员,满足要求,不需要特别声明

    不管是哪个国籍的,写到代码都是Java代码

    中午休息了,大家都去食堂开始吃饭,原形毕露

    老板随便找一个程序员,说一起赛马吧,不可以;因为对方可能是中国或意大利程序员

    多态之向下转型

    将父类的引用变量转换为子类类型,称为向下转型(downcasting)。向下转型后就可以调用子类特有的方法了。

    需要进行强制转换Chinese ch = (Chinese)pro;

    强制转换不是做手术,必须转换成真实子类型,否则ClassCastException;

    向下转型之前肯定发生了向上转型

    为了避免ClassCastException,向下转型之前使用instanceof先判断一下

    pro instanceof Italian 对象 instanceof 类或者接口

    使用instancof的前提:左边的对象和右边的类型在继承树上有上下级关系

    向下转型-代码示例:

    public class TestPoly2 {
        public static void main(String[] args) {
            //基本数据类型的强制转换
            double d = 3.14;
            System.out.println(d);
            int n = (int)d; // 左 < 右  做手术
            System.out.println(n);
            //引用数据类型的强制转换
            Programmer programmer = new Chinese();
            programmer.eat();//多态
            //programmer.playShadowBoxing();
    //        Chinese ch = (Chinese) programmer; // 左<右  不做手术,必须转换成原来//的真实子类型
    //        ch.playShadowBoxing();//
    //        English en = (English)programmer;
    //        en.raceHorse();
            if(programmer instanceof Chinese){
                Chinese ch = (Chinese) programmer;
                ch.playShadowBoxing();
            }else if(programmer instanceof English){
                English en = (English) programmer;
                en.raceHorse();
            }else{
                Italian it = (Italian) programmer;
                it.playFootBall();
            }
            //java.lang.ClassCastException:
            // com.bjsxt.poly0.Chinese cannot be cast to com.bjsxt.poly0.English
            System.out.println(programmer instanceof Chinese); //false
            System.out.println(programmer instanceof English); //true
            System.out.println(programmer instanceof Programmer);//true
            System.out.println(programmer instanceof Object);//true
            //System.out.println(programmer  instanceof  String);
        }
    }
    

    需要注意的点:多态之和方法有关,和属性无关。入下面示例所示。

    多态和属性无关-代码示例:

    public class TestPoly3 {
        public static void main(String[] args) {
            Chinese chinese  = new Chinese();
            System.out.println(chinese.name);
    
            Programmer programmer = new Programmer();
            System.out.println(programmer.name);
    
            Programmer programmer2 = new Chinese();
            System.out.println(programmer2.name); //ChinName  proName
            programmer2.eat();
        }
    }
    

    多态实现简单工厂模式-返回值是父类类型

    不仅可以使用父类做方法的形参,还可以使用父类做方法的返回值类型,真实返回的对象可以是该类的任意一个子类对象。

    代码示例:

    public class TestPoly4 {
        public static void main(String[] args) {
            //自己培养了一个程序员
            //Programmer pro = new Chinese();
            Programmer pro = SxtSchool.getProgrammer("en");
            //让程序员干活
            pro.writeCode();
        }
    }
    class SxtSchool{
            public static Programmer getProgrammer(String type){
                Programmer pro = null;
                if("ch".equals(type)){
                    pro = new Chinese();
                }else if("en".equals(type)){
                    pro = new English();
                }else{
                    pro = new Italian();
                }
                return  pro;
            }
    }
    

    以上代码其实是简单工厂模式的实现,它是解决大量对象创建问题的一个解决方案。将创建和使用分开,工厂负责创建,使用者直接调用即可。简单工厂模式的基本要求是

    定义一个static方法,通过类名直接调用

    返回值类型是父类类型,返回的可以是其任意子类类型

    传入一个字符串类型的参数,工厂根据参数创建对应的子类产品

    相关文章

      网友评论

        本文标题:Java入门姿势 三大特性之一多态性

        本文链接:https://www.haomeiwen.com/subject/ptscgltx.html