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

关键字:多态;多态扩展;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{
            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
            }  
        }

多态成员变量的特点:

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

 

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

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


       
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 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));  
         }    
     }   


   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())
 
返回:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值