精华内容
下载资源
问答
  • 多态和动态绑定

    热门讨论 2017-01-09 21:05:04
    传入的是c (Cat c=new Cat("catname","blue"))是Cat类型的,所以enjoy方法的指针在执行到这句话时,自动指向Cat的enjoy方法,即动态绑定 多态三要素:要有继承;要有重写;父类引用指向子类对象 在此...

    父类Animal:

    class Animal{
    	private String name;
    	Animal(String name){
    		this.name=name;
    	}
    	
    	public void enjoy(){
    		System.out.println("叫声。。。");
    	}
    }
    子类Cat:extends关键字

    class Cat extends Animal{
    	private String eyesColor;
    	Cat(String n,String c){
    		super(n);eyesColor=c;
    	}
    	
    	public void enjoy(){
    		System.out.println("喵~"); //重写父类Animal中的enjoy方法
    	}
    }
    Lady类,人可以养动物:

    class Lady{
    	private String name;
    	private Animal pet;
    	
    	Lady(String name,Animal pet){
    		this.name=name; this.pet=pet;  
    	}
    	
    	public void myPetEnjoy(){pet.enjoy();} //动态绑定机制,Lady方法中传进的pet是什么就调谁的enjoy方法
    }
    main函数:

    public class TestAnimal{
    	public static void main(String args[]){
    		Cat c=new Cat("catname","blue");
    		Lady l1=new Lady("l1",c);  //动态绑定机制
    		l1.myPetEnjoy();
    	}
    }

    Lady l1=new Lady("l1",c); 传入的是c (Cat c=new Cat("catname","blue"))是Cat类型的,所以enjoy方法的指针在执行到这句话时,自动指向Cat的enjoy方法,即动态绑定

    多态三要素:要有继承;要有重写;父类引用指向子类对象

    在此例子中,假如要加入另一种动物狗,另一个人l2养了一只宠物狗,l2的狗高兴的叫了

    只需要添加Dog类:

    class Dog extends Animal{
      private String  furColor;
      Dog(String n,String c){super(n);furColor=c;}
    	
      public void enjoy(){
    	  System.out.println("汪汪汪~");
      }
    }
    适当修改客户端

         	Dog d=new Dog("dahuang","yellow");
    	Lady l2=new Lady("l2",d);
    	l2.myPetEnjoy();
       可见,我们并没有手动修改,在执行Lady l2=new Lady("l2",d);这句话时,自动就找到Dog类中的enjoy方法了。这样一来添加动物也不需修改其他类,更灵活。


    下一篇写抽象类和接口


    展开全文
  • 原标题:多态和动态绑定多态和异常 本文地址:http://www.rrzhai.com/p/7464(转载请注明出处) 浅显易懂,希望看源代码明白什么是oc中多态的可以去看看,

    原标题:多态和动态绑定、多态和异常

    本文地址:http://www.rrzhai.com/p/7464(转载请注明出处)

    浅显易懂,希望看源代码明白什么是oc中多态的可以去看看,

    展开全文
  • Java中的多态和动态绑定

    千次阅读 2016-05-31 18:26:57
    1 定义 Example 动态绑定的内部机制 ...多态和动态绑定大多与继承有关,因为有了继承的出现,才有了父类与子类,然后就是随之而来的方法重写(override),即子类重写父类的方法。另一个出现的就是子

    更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~


    ### 1. 定义

    根据Core Java:

    1. **多态:**一个对象变量可以指示多种实例类型的现象。
    1. **动态绑定:**在运行时刻能够自动选择调用哪个方法的现象。
    2. **签名:**方法名和参数列表构成一个签名

    多态和动态绑定大多与继承有关,因为有了继承的出现,才有了父类与子类,然后就是随之而来的方法重写(override),即子类重写父类的方法。另一个出现的就是子类对象的引用转换为父类对象的引用(此处不需要进行强制转换)。比如:

        public class Son extends Father {
            ...
            
            public static void main(String []args) {
                // 第一种写法
                Son son1 = new Son();
                Father father1 = son1;
                
                // 第二种写法,两种写法类似
                Father father2 = new Son(); // 直接把创建的子类对象的引用赋值给父类变量
            }
        }
        
        
    

    上述代码中的父类变量father1引用的是子类的对象。也就是说,father1余son1引用的都是同一个对象,这个对象就是Son类的对象。但对于变量father1来说,编译器会把其当做Father类的变量,但是JVM当中,把确认其真实的实例类型(Son类)。

    子类转为父类可以,但是反过来不行,比如:

        Father father3 = new Father();
        Son son3 = father3;
    

    此处是把父类创建的一个对象(father3)的引用赋给子类变量(son3),在继承当中,这是不被允许的。试想:若此赋值语句成功,那么son3引用的对象其实是father3,但是son3其本身又被声明为Son类,此时在Son类中若有一个额外的新方法(eg: MethodOfSon(){…}),那么son3就可以调用该方法,但是其引用的对象是没有这个方法的,会造成混乱,所以此赋值方式不合适。

    在类的继承之外,还有同一个类内部的方法重载(overloading),同一个方法名,因参数类型和参数个数不同,构成不同的签名。另外,签名不包含返回类型。

    2. Example

    Employee.java

        public class Employee
        {
           private String name;
           private double salary;
           private Date hireDay;
        
           public Employee(String n, double s, int year, int month, int day)
           {
              name = n;
              salary = s;
              GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
              hireDay = calendar.getTime();
           }
        
           public String getName()
           {
              return name;
           }
        
           public double getSalary()
           {
              return salary;
           }
        
           public Date getHireDay()
           {
              return hireDay;
           }
        
           public void raiseSalary(double byPercent)
           {
              double raise = salary * byPercent / 100;
              salary += raise;
           }
        }
    

    Manager.java

        public class Manager extends Employee
        {
           private double bonus;
        
           /**
            * @param n the employee's name
            * @param s the salary
            * @param year the hire year
            * @param month the hire month
            * @param day the hire day
            */
           public Manager(String n, double s, int year, int month, int day)
           {
              super(n, s, year, month, day);
              bonus = 0;
           }
        
           public double getSalary()
           {
              double baseSalary = super.getSalary();
              return baseSalary + bonus;
           }
        
           public void setBonus(double b)
           {
              bonus = b;
           }
        }
    

    ManagerTest.java

        public class ManagerTest
        {
           public static void main(String[] args)
           {
              // construct a Manager object
              Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);
              boss.setBonus(5000);
        
              Employee[] staff = new Employee[3];
        
              // fill the staff array with Manager and Employee objects
        
              staff[0] = boss;
              staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
              staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15);
              
              
              // print out information about all Employee objects
              for (Employee e : staff)
                 System.out.println("name=" + e.getName() + ",salary=" + e.getSalary());
           }
        }
    
    其结果如下:
    name=Carl Cracker,salary=85000.0
    name=Harry Hacker,salary=50000.0
    name=Tommy Tester,salary=40000.0

    说明类Manager继承类Employee,在Manager内部重写了getSalary()方法,并新添加了setBonus()方法。

    在main()函数中,Employee类型的数组staff包含了3个元素,第一个元素staff[0]包含的Manager类对象的引用,其与boss引用同一个Manager对象。staff[1]和staff[2]包含的是Employee类变量,分别指向不同的Employee类对象。

    从结果看出,staff[0]的getSalary()方法,调用的Manager里面的方法,而staff[1]和staff[2]都是调用的Employee类中的getSalary()方法。staff[0]虽然声明的是一个Employee变量,但是其引用的对象却是Manager类对象,所以会首先在Manager类中查找是否有完全匹配的getSalary()方法(有可能存在重载的情况),然后再在父类中查找是否有完整的getSalary()方法。

    还一个需要注意的地方:编译器会认为staff[0]是一个Employee对象,所以对于以下的调用方式,程序会出错:

        staff[0].setBonus(100);
    

    同样,如果有如下的赋值,也是错误的:

        Manager manager1 = staff[0];
    

    因为从编译器的角度来看,这两个是不同的类型,所以需要进行强制类型转换:

        Manager manager1 = (Manager) staff[0];
    

    这种方式,看似这样很合理,因为staff[0]引用的是Manager对象,让manager1变量也应用这个对象,这样赋值好像也没什么不对,但是同样编译器报错。因为编译器认为staff[0]是属于Employee类型的,而Manager类是Employee类的子类,两者是不同的类型,不能直接赋值,必须要强制类型转换。

    按照这个逻辑,以下的赋值语句,编译器也是通过的:

        Manager manager2 = (Manager) staff[1];
    

    虽然编译器是通过的,但是在程序运行时,也会报错"ClassCastException"。原因在于staff[1]引用的对象是Employee类型的,也就是说,该Employee对象也能调用子类Manager当中的新方法 s e t B o n u s ( x ) setBonus(x) setBonus(x),这是错误的。所以,Java当中,把父类对象强制转换为子类对象是不被允许的,反过来可以。

    其实,上面的一段话,是从底层的角度对多个对象的逻辑关系进行的分析,实际上,Java虚拟机已经帮我们做了安全检查。只需要使用 i n s t a n c e o f instanceof instanceof运算符,就可以确保赋值安全。

        Manager manager2;
        if(staff[1] instanceof Manager) {
            manager2 = staff[1];
        }
    

    所以,***在将超类对象转为子类对象时,一定要进行 i n s t a n c e o f instanceof instanceof检查***。

    在上面的例子中,staff[0]就是一个多态的例子,有继承,就有多态。和多态分不开的一个就是动态绑定。动态绑定和是静态绑定相对应的,一个是在编译的时候就知道用什么方法,还一个就是在运行时刻才知道调用哪个方法。

    有private,static,final修饰的方法,或者构造函数,都是静态绑定。

    3. 动态绑定的内部机制

    首先理解方法表的概念:

    方法表:除了private、static、final修饰的方法外,其他的能够参与动态绑定的实例方法。

    对于动态绑定来说,每次在类中找对应的方法总是低效的,时间开销大,所以需要为每个类生成一个方法表,这样可以直接在类的方法表中寻找。

    过程如下:

    1. 首先编译器确定对象的声明类型和方法名。然后找当前类中方法名字匹配的所有方法(由于重载,可能存在多个),然后在其父类中也找类似的属性为public的方法;
    2. 编译器查看调用方法的参数类型,先在本类中找,然后在超类中找,这一过程称为***重载解析(overloading resolution)***。若没找到,或在同一个类中找到多个,均报错。
    3. 若为private、static或者final修饰的方法,为静态绑定,可直接知道调用的是哪个方法,此情况下就省去了剩下的步骤;
    4. 在程序运行时,JVM会根据对象的实际类型从方法表中调用最合适的方法。

    note:

    • 动态绑定只针对类的方法,对数据域无效,因为根据类的封装特性,数据域都是私有的,即使是子类,也无法访问。
    • 方法表存储在JVM中的方法区。

    参考:


    \qquad \qquad \qquad \qquad —— 2016.5.31

    更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

    展开全文
  • Title:重载、多态和动态绑定——Overloading、Ploymorphism&Dynamic binding 【Section one】  对于面向对象编程语言,重载、多态和动态绑定是非常重要的概念,并且其中细节容易误解,在此,我写下这篇...

    Title:重载、多态和动态绑定——OverloadingPloymorphism&Dynamic binding


    【Section one】

        对于面向对象编程语言,重载、多态和动态绑定是非常重要的概念,并且其中细节容易误解,在此,我写下这篇文章既为总结,亦为学习。

    【Section two】

    一、重载

       在Java中,方法的名称和形参列表称为方法的签名,只要签名相同便视为同一方法,因此,在同一个类中不允许出现签名相同的方法,如:public int getSalary()与public double getSalary()在同一个类中定义便会报错,因为按照Java的语法规则,这两个方法的签名是相同的,则视为重复定义!!

       所谓重载,指的是方法的名字相同而形参列表不同(即签名不同),如:public void setSalary(double s)与public void setSalary(int s)就是两个不同的方法,当对象调用名为setSalary的方法时,编译器会查看调用这个方法时提供的参数类型,如果在所有名为setSalary的方法中存在于提供参数类型完全匹配的方法,则编译器自动选择这个方法。如下例子,编译会根据调用add方法时提供的参数类型自动寻找完全匹配的方法。

    public double add(double num1,double num2)
    	{
    		return num1+num2;
    	}
    public int add(int num1,int num2)
    	{
    		return num1+num2;
    	}
    
    
    System.out.println(boss.add(100, 200));
    System.out.println(boss.add(100.1, 200.0));
    输出结果:

         300
         300.1

    二、多态

        多态的定义:一个对象变量可以指示多种实际类型的现象。在Java中,对象变量是多态的,一个类Temp的对象变量既能引用Temp类的对象,也能引用Temp类的任意子类的对象。虽然如此,但是超类对象变量引用其子类对象的时候需要注意几个问题:(我们以Employee类和Manager类为例,其中Employee为Manager的超类,如下程序,p为超类对象变量,boss为子类对象变量,p=boss,使得p引用了其子类对象)

        1、引用子类对象的超类对象变量不能调用子类中新定义的方法(即超类中不存在同样签名的方法);

        2、引用子类对象的超类对象变量可以调用子类未定义而定义于超类中的方法(显然,因为这是继承而来的);

        3、若子类中定义了与超类签名相同的方法,子类中的该方法将覆盖超类中的方法,即:引用子类对象的超类对象变量调用子类和超类中均有定义且签名相同的方法时,将调用子类中的该方法。

    public class Test 
    {
    	
    	public static void main(String[] args) 
    	{
    		Employee p=new Employee("Calvin",44,32345.9);
    		Manager boss=new Manager("Sue",23,3000,2000);
    		
    		p=boss;//超类对象变量引用子类对象
    		p.setSalary(2000);//调用超类Employee中的getSalary()方法(第二条)
    		p.getSuperSalary();//将报错,P[0]无法调用只存在于子类中的方法(第一条)
    		System.out.println(p.getSalary());//调用的是子类中的getSalary方法(第三条)
    	}
    }
    
    class Employee
    {
    	private String name;
    	private int age;
    	private double salary;
    	
    	public Employee(String aname,int aage,double asalary)
    	{
    		name=aname;
    		age=aage;
    		salary=asalary;
    	}
    	
    	public double getSalary()
    	{
    		return salary;
    	}
    	
    	public void setSalary(double salary)
    	{
    		this.salary=salary;
    	}
    }
    
    class Manager extends Employee
    {
    	private double bonus;
    	public Manager(String name,int age, double salary,double bonus)
    	{
    		super(name,age,salary);
    		this.bonus=bonus;
    	}
    	
    	public double getSalary()
    	{
    		return super.getSalary()+bonus;
    	}
    	
    	public double getSuperSalary()
    	{
    		return super.getSalary();
    	}
    	
    }

    三、动态绑定

        在Java中的定义:在运行时能够自动选择调用哪个方法的现象称为动态绑定。一个对象调用一个方法时,编译器会首先查看对象声明的类型和所调用的方法的名,需要注意的是,在该对象所属的类及其超类中可能存在多个方法具有相同的名字,编译器会列举所有可调用的方法作为候选;然后根据调用方法所提供的参数类型进一步从这些候选方法中寻找完全匹配的方法,这一步也就是重载;到此,完全匹配的方法并不一定是唯一的,因为该对象所属的类及其超类中可能定义了相同签名的方法,这时候就有一个“覆盖”的问题,即:子类中的这个签名的方法将会覆盖掉其超类中相同签名的方法;最后,该对象才能确定调用的是哪个方法。这个过程称为动态绑定,说得直白点,对象调用某个方法时,编译器是不能直接确定的,而是一个动态判定的过程。


    【Section three】

        补充:与动态绑定相对应,还有一种静态绑定(Static Binding),也就是编译器可以准确的知道调用的方法,这类方法包括private、final、static以及构造器。

    展开全文
  • 1.多态和动态绑定动态绑定:在C++中,当我们使用基类的引用或指针调用一个虚函数时将发生动态绑定多态:多态性可以简单地概括为“一个接口,多种方法” 多态目的:为了接口重用。对于动态多态来说就是不论...
  • 动态绑定:指在多态的情况下,在执行期间(非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法,指这样一种过程。 另外,马士兵在他的java基础视频教学中说“多态就是动态绑定”.....感觉不太...
  • //在运行时能够自动的选择调用哪个方法的现象称为动态绑定 //首先调用自己的getSalary()方法,自己未定义该方法则调用父类的同名方法 System.out.println(e.getSalary()); } } } 运行结果: 基本...
  • FAQ 5.11 多态和动态绑定(polymorphism and dynamic binding)C++的这种特点使新的代码多少可以替代一些旧的代码:面向对象程序强大的真正原因不在于继承;而在于它可以将继承类对象当作基类对象来对待,支持这个特性的...
  • java多态和动态绑定

    2016-04-11 23:55:45
    java的继承使用关键字extends。 例如:class B extends A{…}表示类B继承类A。 java多态存在的三个必要条件:要有继承、要有重写、父类变量引用子类对象。 当使用多态方式调用方法时: ...静态绑定(static
  • 核心内容: 1. 多态 2.动态绑定 3. 动态类型 ...土豆高清视频播放地址: 3.6 OC多态和动态绑定 百度云网盘视频下载地址:http://pan.baidu.com/share/link?shareid=63870&uk=1711799154
  • 先放上一段测试代码: People [ ] stuff = new ...在遍历stuff数组的时候,可以用u既表示People类又表示RichPeople类,一个变量表示多种实际类型,这种现象就是...java的动态绑定与静态绑定(彻底理解多态与重载)
  • 网上很多的文章并不能让我真正的理解多态,准备深入分析一下Java多态o( ̄ヘ ̄o#)。
  • 在Java中,如果一个类B...该现象就是后期绑定,即在运行时根据对象的类型进行绑定,也叫动态绑定或者运行时绑定。 这样做的好处是具有拓展性,调用的时候可以仅仅使用父类调用,而不用关心子类到底是什么,只要子
  • 最近深入学习java,看到了动态绑定和多态这一章节,但遗憾的是,大部分的相关文章都停留于表面文字的描述。不得已,最后google了几篇英文文章,在此总结下这个问题。 一、静态绑定和动态绑定的区别 在Java中,当...
  • 所谓动态绑定,指的是当调用一个子类实例的父类方法时,系统能够自动识别调用【该子类自身对父类方法的实现】; 此处带来案例,战狼 @案例:战狼,需求说明: 为帝国创建一支军队,包含骑兵、弓箭手、法师 ...
  • id类型,可称为动态类型 id car2; Car car; 将car=>car2 ,则car2自动被识别为Car类型,可以使用Car类的方法。 多态:父类声明的变量指向子类的对象。 比如:id car; car=[[奔驰 alloc] init]; [car 奔驰的...
  • 主要介绍了Java多态动态绑定原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 64,968
精华内容 25,987
关键字:

多态和动态绑定