Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Language agnostic 如何在动态语言中实现类?_Language Agnostic_Programming Languages - Fatal编程技术网

Language agnostic 如何在动态语言中实现类?

Language agnostic 如何在动态语言中实现类?,language-agnostic,programming-languages,Language Agnostic,Programming Languages,如何在动态语言中实现类 我知道Javascript使用的是一个原型模式(在“某处”有一个未绑定JS函数的容器,当通过对象调用它们时,这些函数是绑定的),但我不知道它在其他语言中是如何工作的 我对此很好奇,因为我想不出一种有效的方法,通过复制每个实例的成员来拥有本机绑定方法而不浪费内存和/或cpu (通过绑定方法,我的意思是以下代码应该可以工作:) 这在很大程度上取决于语言和实现。我会告诉你我对CPython和PyPy的了解 总的想法是这样的,这也是CPython在大部分情况下所做的: 每个对象都

如何在动态语言中实现类

我知道Javascript使用的是一个原型模式(在“某处”有一个未绑定JS函数的容器,当通过对象调用它们时,这些函数是绑定的),但我不知道它在其他语言中是如何工作的

我对此很好奇,因为我想不出一种有效的方法,通过复制每个实例的成员来拥有本机绑定方法而不浪费内存和/或cpu

(通过绑定方法,我的意思是以下代码应该可以工作:)


这在很大程度上取决于语言和实现。我会告诉你我对CPython和PyPy的了解

总的想法是这样的,这也是CPython在大部分情况下所做的:

  • 每个对象都有一个类,特别是对该类对象的引用
  • 除了实例成员(显然存储在单个对象中)之外,该类还有成员。这包括方法,因此方法没有每个对象的成本
  • 类具有由继承关系确定的方法解析顺序(MRO),其中每个基类只出现一次。如果我们没有多重继承,这将只是对基类的引用,但是这种方式很难动态地理解MRO(每次都必须从派生最多的类开始)
  • (类也是对象,它们本身也有类,但现在我们将对此进行说明。)
  • 如果对象上的属性查找失败,将按照MRO指定的顺序在MRO中的类上查找相同的属性。(这是默认行为,可以通过定义像
    \uuuuu getattr\uuuu
    \uuu getattribute\uuuu
    这样的神奇方法来更改)
  • 到目前为止还很简单,并不是对绑定方法的真正解释。我只是想确定我们谈论的是同一件事。缺少的部分是描述符。在语言参考的“deep magic”一节中定义了,但简单的故事是,通过
    \uuuu get\uuu
    方法,类的查找结果可能会被它所生成的对象劫持。更重要的是,这个
    \uuuuuu get\uuuuu
    方法被告知是在实例上还是在“所有者”(类)上开始查找

    在Python2中,我们有一个丑陋且不必要的
    UnboundMethod
    描述符(除了
    \uuuu get\uuuu
    方法之外),它简单地包装函数,在
    类上抛出错误。如果
    self
    不是可接受的类型,则方法(self)
    。在Python3中,
    \uuuuu get\uuuu
    只是所有函数对象的一部分,而未绑定的方法就不存在了。在这两种情况下,
    \uuu get\uuu
    方法在您查找类时返回自身(因此您可以使用
    class.method
    ,这在少数情况下很有用),在您查找对象时返回“绑定方法”对象。这个绑定方法对象只不过是存储原始函数和实例,并将后者作为第一个参数在其
    \uuuuu调用\uuuu
    中传递给前者(覆盖函数调用语法的特殊方法)

    因此,对于CPython:虽然绑定方法有成本,但它比您想象的要小。在空间方面只需要两个引用,CPU成本仅限于较小的内存分配,并且在调用时需要额外的间接寻址。但是请注意,这种代价适用于所有方法调用,而不仅仅是那些实际使用绑定方法特性的方法调用
    a.f()
    必须调用描述符并使用其返回值,因为在动态语言中,我们不知道是否对其进行了猴子补丁以执行不同的操作

    在PyPy中,事情更有趣。由于它是一个不会在正确性上妥协的实现,因此上述模型在语义推理方面仍然是正确的。然而,它实际上更快。除了JIT编译器内联然后在大多数情况下消除上面描述的整个混乱之外,它们还可以在字节码级别解决这个问题。在
    a.f()
    的情况下,有两种方法保留了语义,但省略了绑定方法对象的分配。还有一种方法可以简化查找过程,但需要一些额外的簿记(尽管一些簿记已经为JIT完成)

    class Foo { function bar() : return 42; };
    
    var test = new Foo();
    var method = test.bar;
    method() == 42;