Java基础08:多态;多态扩展;object类;多态的特点

来源:互联网 发布:日语段落翻译软件 编辑:程序博客网 时间:2024/05/29 18:37
关键字:多态;多态扩展;object类;多态的特点

一、多态

    定义:某一类事物存在的多种体现形态。例如,人的体现:男人、女人。

    例如,动物中的猫、狗。猫这个对象对应的类型是猫类型。猫 x = new 猫();。同时,猫也是动物的一种,也可以把猫成为动物。例如,动物 x = new 猫();,必须有继承关系或实现关系才行。动物是猫和狗具体事物中抽象出来的父类。父类型引用指向了子类对象。实体可以具备其他类型,具备多种形态,即多种局部变量可以指向同一种实体。接口的引用也可以指向子类的对象,例如,PCI p = new NetCard();,也是多态。

    函数也具备多态性,例如,重载和覆盖。

    Animal a = new Cat();类型提升,向上转型,把猫类型引用提升为动物类型引用。

    Cat c = (Cat)a; c.catchMouse();强制转换,将父类的引用转成子类类型。向下转型。不允许将父类的实体转成子类类型。例如,Animal a = new Animal();Cat c = (Cat)a;因为子类具有一些父类没有的功能。

实体不能改变类型,内部封装的数据会被破坏。能改变的是栈中的数据,但不能改变堆中的数据。当父类引用指向了子类的对象时,该引用可以被提升,也可以被强制转换。多态都是子类的对象的指向在变化。

instanceof 判断对象是否属于类。使用:一是子类型有限;二是确定属于哪种子类型,确定调用的方法。

    1. 多态的表现形式

    父类或者接口的引用可以指向自己的子类对象。例如,Animal a = new Cat();。接口的引用也可以指向子类的对象,降低了程序的耦合性。

    2. 多态的前提

    类与类直接必须有关系,要么继承,要么实现

    要有覆盖操作。子类的对象传入后,会覆盖父类的方法。

    3. 多态的利弊

    好处:提高了程序的扩展性和后期维护性。

    弊端:只能使用父类的引用访问父类的成员。

    4. 多态的应用

可以指挥一批对象执行方法,找到了对象的共同所属类型。建立父类后,在建立相应的工具类,在主函数中直接调用工具类即可。对类型进行抽取导致多态的产生,操作同一个大类型,对大类型中的所有子类型都可以操作。

  
abstract class Animal{        public abstract void eat();                    }    class Cat extends Animal{        public void eat(){            System.out.println("吃鱼");        }        public void catchMouse(){            System.out.println("抓老鼠");        }    }    class Dog extends Animal{        public void eat(){            System.out.println("吃骨头");        }        public void kanJia(){            System.out.println("看家");        }    }    class Pig extends Animal{        public void eat(){            System.out.println("吃饲料");        }        public void gongDi(){            System.out.println("拱地");        }    }    public class Demo{          public static void main(String[] args){                  /*老方式           Cat c = new Cat();           c.eat();           Dog d = new Dog();           d.eat();           function(c);           function(d);           function(new Cat());           function(new Dog());           */        //多态            Animal a = new Cat();    //类型提升,向上转型,子类向父类转            a.eat();            //如果想要调用猫的特有方法时,如何操作?            //强制将父类的引用,转成子类类型,向下转型            Cat c = (Cat)a;            //既能向上转,也能向下转,强制将父类的引用,转成子类类型,向下转型,前提是,  创建时,他是引用的是他的子类。我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被转换                                    //多态自始至终都是子类对象在做着变化            c.catchMouse();            // Animal a = new Animal();                // Cat c = (Cat)a;//千万不要出现这样的操作,就是将父类对象转成子类类型。                            //我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换            function(new Cat());            function(new Dog());            function(new Pig());        }          /*       public static void function(Cat c){           c.eat();       }       public static void function(Dog d){           d.eat();       }       public static void function(Pig d){           d.eat();       }       */        //多态应用        public static void function(Animal a){            a.eat();            if(a instanceof Cat){        //  instanceof 判断 该对象 是哪个类的 对象                Cat c = (Cat)a;                    c.catchMouse();            }else if(a instanceof Dog){                            }        }    } 
/*       基础班学生:           学习,睡觉       高级班学生:           学习睡觉              可以将这两类事物进行抽取   */    abstract class Student{        public abstract void study();        public void sleep(){            System.out.println("躺着睡");        }    }    class BaseStudent extends Student{        public void study(){            System.out.println("base study");        }        public void sleep(){            System.out.println("坐着睡");        }    }    class AdvStudent extends Student{        public void study(){            System.out.println("adv study");        }    }    class DoStudent{        public void doSome(Student stu){            stu.study();            stu.sleep();        }    }        public class Demo{          public static void main(String[] args){              Student bs = new BaseStudent();            Student as = new AdvStudent();            doSome(bs);            doSome(as);            doSome(new BaseStudent());            doSome(new AdvStudent());            DoStudent ds = new DoStudent();            ds.doSome(new BaseStudent());            ds.doSome(new AdvStudent());        }          public static void doSome(Student stu){            stu.study();            stu.sleep();        }    }   


      5、多态出现在代码中的特点(使用注意)

在多态中(Fu f = new Zi();)非静态成员函数的特点:

编译时期:参阅引用变量所属的类中(父类)是否有调用的方法,如果有,编译通过;如果没有,编译失败。

运行时期:参阅对象所属的类中(子类)是否有调用的方法。对象在调用方法。找的是方法区中的非静态区,参考对象。相当于和this绑定,进而和对象绑定,即“动态绑定”。

简单总结:成员函数在多态调用时,编译看左边,运行看右边。相当于过滤了两遍。此情况最多见,因为有覆盖操作。

       
class Fu{             void method1(){                 System.out.println("fu method_1");             }             void method2(){                 System.out.println("fu method_2");             }         }         class Zi extends Fu{             void method1(){                 System.out.println("zi method_1");             }             void method3(){                 System.out.println("zi method_3");             }         }         public class Demo{               public static void main(String[] args){                                Fu f = new Zi();                 // z.method1();        zi-1                 // z.method2();        fu-2                 // z.method3();        错误                                                   // Zi z = new Zi();                 // z.method1();        zi-1                 // z.method2();        fu-2                 // z.method3();        zi-3             }           }  

/*       基础班学生:           学习,睡觉       高级班学生:           学习睡觉              可以将这两类事物进行抽取   */    abstract class Student{        public abstract void study();        public void sleep(){            System.out.println("躺着睡");        }    }    class BaseStudent extends Student{        public void study(){            System.out.println("base study");        }        public void sleep(){            System.out.println("坐着睡");        }    }    class AdvStudent extends Student{        public void study(){            System.out.println("adv study");        }    }    class DoStudent{        public void doSome(Student stu){            stu.study();            stu.sleep();        }    }        public class Demo{          public static void main(String[] args){              Student bs = new BaseStudent();            Student as = new AdvStudent();            doSome(bs);            doSome(as);            doSome(new BaseStudent());            doSome(new AdvStudent());            DoStudent ds = new DoStudent();            ds.doSome(new BaseStudent());            ds.doSome(new AdvStudent());        }          public static void doSome(Student stu){            stu.study();            stu.sleep();        }    }   


多态成员变量的特点:

无论编译还是运行,都参考左边(引用变量所属的类)。主要是针对同名变量的情况,一般很少发生。静态绑定。

 

多态中静态成员(变量和函数)的特点:

无论编译和运行都参考左边,即参考引用所属的类。静态函数随类加载,不所属于对象,所以参考引用型变量的类,相当于用父类直接调用。找的是方法区中的静态区,不参考对象。或者认为,静态方法一进内存,就已经被绑定到方法所属类上了,即“静态绑定”。没有覆盖,各走各的方法。


       
class Fu{             int num = 5;             static void method4(){                 System.out.println("fu method_4");             }         }         class Zi extends Fu{             int num = 8;             static void method4(){                 System.out.println("zi method_4");             }         }         public class Demo{               public static void main(String[] args){                                Fu f = new Zi();                 f.num;                //为 5                  Zi z = new Zi();                 z.num;                //为 8                  f.method4();        //fu                 z.method4();        //zi             }           }   


接口型引用指向自己的子类对象。虽然不能产生对象,但可以产生引用,可以指向对象。类——》接口——》主程序,将相似的类中的方法抽象出来放在接口,使得类与主程序没有关系;只要类实现了接口,接口的引用就能指向类的对象;更改类的话,只要更改接口的引用,使其指向新类,即可调用新类的方法,接口和主程序无需变化。降低了主程序和某些类的耦合性,类似电源插排比直接接电源方便。

/*扩展差        class MainBoard{            public void run(){                System.out.println("MainBoard run");            }            public void useNetCard(NetCard c){                c.open();                c.close();            }        }        class NetCard{            public void open(){                System.out.println("NetCard open");            }            public void close(){                System.out.println("NetCard close");            }        }        public class Demo{              public static void main(String[] args){                  MainBoard mb = new MainBoard();                mb.run();                mb.useNetCard(new NetCard());            }          }         */         interface Pci{             public void open();             public void close();         }         class MainBoard{             public void run(){                 System.out.println("MainBoard run");             }             public void usePci(Pci p){    //Pci p = new NetCard(); 接口型引用指向自己的子类对象                 if(p!=null){                     p.open();                     p.close();                 }             }         }         class NetCard implements Pci{             public void open(){                 System.out.println("NetCard open");             }             public void close(){                 System.out.println("NetCard close");             }         }         class SoundCard implements Pci{             public void open(){                 System.out.println("SoundCard open");             }             public void close(){                 System.out.println("SoundCard close");             }         }         public class Demo{               public static void main(String[] args){                   MainBoard mb = new MainBoard();                 mb.run();                 mb.usePci(new NetCard());                 mb.usePci(new SoundCard());             }           }   


 二、多态的扩展示例—— 数据库的操作
    1、步骤
        (1)、连接数据库
        (2)、操作数据库
            (1)、c:create
            (2)、r:read
            (3)、u:update
            (4)、d:delete
        (3)、关闭数据库
    2、例子
     
interface UserInfoDao{           public void add(User user);           public void delete(User user);       }       class UserInfoByHibernate implements UserInfoDao{           public void add(){               1、连接数据库               2、使用sql添加语句添加数据               3、关闭连接           }           public void delete(User user){               1、连接数据库               2、使用sql添加语句删除数据               3、关闭连接           }       }       public class Demo{             public static void main(String[] args){                 //UserInfoByJDBC ui = new UserInfoByJDBC();               UserInfoDao ui = new UserInfoByHibernate();               ui.add(user);               ui.delete(user);           }         }        /*      class UserInfoByJDBC{          public void add(){              1、连接数据库              2、使用sql添加语句添加数据              3、关闭连接          }          public void delete(User user){              1、连接数据库              2、使用sql添加语句删除数据              3、关闭连接          }      }      class UserInfoByHi{          public void add(){              1、连接数据库              2、使用sql添加语句添加数据              3、关闭连接          }          public void delete(User user){              1、连接数据库              2、使用sql添加语句删除数据              3、关闭连接          }      }      */  


三、Object类-equals()
    1、类 Object 是类层次结构的跟雷。每个类都使用 Object 作为超类,所有对象(包括数组)都实现这个类的方法。
    2、Object :是所有对象的直接或者间接父类,传说中的上帝
        (1)、该类中定义的是所有对象都具备的功能
        (2)、Object没有super
        (3)、java认为所有对象都具备比较性
    3、equals方法,指示其他某个对象是否与此对象“相等”。 
        (1)、实际是比较的对象引用的地址
    4、Objedt 类中已经提供了对对象是否相同的比较方法
        (1)、如果自定义类中也有比较相同的功能,没有必要重新定义
        (2)、只要沿袭父类中的功能,建立自己特有比较内容即可,这就是覆盖
        (3)、多态的时候,使用子类特有成员,要注意向下转型
    5、例子
     
class DemoTest{           private int num;           DemoTest(int num){               this.num = num;           }           public boolean equals(Object obj){               if(obj instanceof DemoTest){                   DemoTest d = (DemoTest)obj;                   return this.num == d.num;               }           }       }       public class Demo{             public static void main(String[] args){                 //UserInfoByJDBC ui = new UserInfoByJDBC();               DemoTest d1 = new DemoTest(1);               DemoTest d2 = new DemoTest(2);               System.out.println(d1.equals(d2));           }         }   



四、toString
public String toString()返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。 
Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于: 


getClass().getName() + '@' + Integer.toHexString(hashCode())
 
返回:

该对象的字符串表示形式。

对于这些方法,在创建类的时候都要做覆盖操作,建立自身的各种方法。

原创粉丝点击