静态绑定和动态绑定有什么区别?

Kin*_*tor 23 programming-languages language-design

绑定时间可以分为两种类型:静态和动态.静态绑定和动态绑定有什么区别?

你能举个简单的例子来进一步说明吗?

Joh*_*lla 27

在最一般的术语中,静态绑定意味着在编译时解析引用.

Animal a = new Animal();
a.Roar(); // The compiler can resolve this method call statically.
Run Code Online (Sandbox Code Playgroud)

动态绑定意味着在运行时解析引用.

public void MakeSomeNoise(object a) {
   // Things happen...
   ((Animal) a).Roar(); // You won't know if this works until runtime!
}
Run Code Online (Sandbox Code Playgroud)

  • 您的后一个示例仍然是静态绑定.类型转换可能会或可能不会成功,但如果类型转换成功,即使`Roar`是虚拟方法,该代码将被绑定到()`静态地`Animal.Roar相关联的虚表插槽.使用任一当新的`dynamic`类型,或者通过使用反射动态结合仅发生在C#(例如`a.GetType().GetMethod( "吼").调用(一个,NULL)`).后者适用于实现名为`Roar`的无参数方法的任何类型,并返回最派生的实现(即使基本实现是非虚拟的). (3认同)

Dav*_*uda 6

它取决于何时发生绑定:在编译时(静态)或在运行时(动态).调用简单类方法时使用静态绑定.当您开始处理类层次结构和虚方法时,编译器将开始使用所谓的VTABLE.那时编译器并不确切地知道要调用什么方法,它必须等到运行时才能确定要调用的正确方法(这是通过VTABLE完成的).这称为动态绑定.

有关更多详细信息和参考,请参阅有关虚拟表的 Wikipedia文章.


Zee*_*bir 5

我遇到了 quora 用户“Monis Yousuf”的完美答案。他完美地解释了这一点。我把它放在这里供其他人使用。

\n\n

绑定主要是面向对象编程中与多态性相关的概念。

\n\n

首先,了解什么是多态。书上说它的意思是“一名多形”。确实如此,但太抽象了。让我们举一个现实生活中的例子。你去看“医生”,医生可能是眼科专家、耳鼻喉科专家、神经外科医生、顺势疗法医生等。

\n\n

这里的“医生”是一个名字,可以有多种类型;每个人都执行自己的功能。这就是现实生活中的多态性。

\n\n

函数重载:这个概念描述了静态绑定。函数重载可以粗略地定义为,两个或多个具有相同名称但签名不同(包括参数数量、参数类型、不同返回类型)的方法(函数)称为重载方法(或函数)。

\n\n

假设您必须计算矩形和圆形的面积。请参阅下面的代码:-

\n\n
class CalculateArea {\n\n    private static final double PI = 3.14;\n\n    /* \n       Method to return area of a rectangle \n       Area of rectangle = length X width\n    */\n    double Area(double length, double width) {\n        return (length * width);\n    }\n\n    /*\n      Method to return area of circle\n      Area of circle = \xcf\x80 * r * r\n    */\n    double Area(double radius) {\n        return PI * radius * radius;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在上面的代码中,有两个具有不同参数的方法“Area”。这种情况属于函数重载。

\n\n

现在,真正的问题是:这个静态绑定是如何实现的?

\n\n

当您在代码中调用上述任何函数时,您必须指定要传递的参数。在这种情况下,您将通过:

\n\n
    \n
  • 两个 double 类型的参数[将调用第一个方法,\n计算矩形]
  • \n
  • double 类型的单个参数 [这将调用第二个方法,计算圆的面积]
  • \n
\n\n

因为,在编译时,java 编译器可以确定要调用哪个函数,因此它是编译时(或静态)绑定。

\n\n

函数重写:函数重写是继承中显示的一个概念。大致可以定义为:当父类中存在一个方法,并且其子类也有相同签名的方法时,称为函数重写。[还有更多内容,但为了简单起见,我写了这个定义]下面的代码会更容易理解。

\n\n
class ParentClass {\n    int show() {\n        System.out.println("I am from parent class");\n    }\n}\n\nclass ChildClass extends ParentClass{\n    int show() {\n        System.out.println("I am from child class");\n    }\n}\n\nclass SomeOtherClass {\n    public static void main (String[] s) {\n        ParentClass obj = new ChildClass();\n        obj.show();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在上面的代码中,该方法show()被重写,因为父类和子类中都存在相同的签名(和名称)。

\n\n

在第三个类中SomeOtherClass,类型的引用变量(obj)ParentClass保存了ChildClass的对象。show(接下来,从同一引用变量 (obj) 调用方法)。

\n\n

再次,同样的问题:这个动态绑定怎么样?

\n\n

在编译时,编译器检查引用变量的类型ParentClass,并检查该方法是否show()存在于此类中。一旦检查到这一点,编译就成功了。

\n\n

现在,当程序运行时,它会看到该对象是 的ChildClass,因此它show()运行ChildClass. 由于此决定是在运行时进行的,因此称为动态绑定(或运行时多态性)。

\n\n

原始答案链接

\n