好吧,让我们看看...
我突然想知道为什么我们有非静态函数/方法?方法不是对象的属性(如属性/数据成员),并且该类的所有实例都使用相同的方法,那么为什么静态方法和非静态方法之间存在差异?
需要注意的关键是它是概念上的差异。实例方法在被调用时与特定对象“关联” ——它具有某种形式的“this”上下文——而静态方法则不是。
这是否意味着当一个对象被实例化时,它拥有方法的副本——对于该类的所有实例来说这些方法完全相同?
这取决于语言,但通常不会。
例如,在 Java 中,类的所有实例共享的方法只有一个副本。方法不是类实例数据的“一部分”。在 JavaScript 中,可以通过使用 [[prototype]] 链或在较小程度上通过在不同实例中为相同方法重用相同函数对象来获得这种共享。(然而,也可以在 JavaScript 中为每个新实例创建一个新方法,但这是程序员的选择。)
在 Java 中,发送“消息”以调用实例方法;也就是说,它查看特定类型并将消息与适当的“this”实例一起发送给它。(由于虚拟调度,这比这更复杂,但是......要注意的关键是只有一个特定类型的方法的副本被加载到内存中。)
在 JavaScript 中,方法是一等值动态绑定到接收者(即“this “ inside 是根据它的调用方式建立的)。Python 的工作方式与 JavaScript 类似,因为方法是被获取和调用的一流函数(但方法仍然“绑定”到一个类,这与 JavaScript 不同)。Ruby 的工作方式更像 Java,因为“发送消息”反过来调用一个方法(这不是Ruby 中的一等值)并将上下文隐式关联到接收者。所有这些语言都支持各种形式的“子类化”(你可以怎么称呼它)来调整 MRO 并共享实例通用的方法。
每个对象的方法都是一样的,只是不同的对象调用了方法,那我们为什么要让方法成为对象的一部分呢??为什么方法不能只存储一次(如静态方法),然后在使用“this”时我们在相关对象上执行?对于每个实例,将非静态方法存储为对象的一部分似乎很愚蠢。
这就是许多语言所做的——包括 Java、C++、Python(通常)和 Ruby(通常)和 JavaScript(通常),它是节省内存和开销的一个非常有效的点。
快乐编码!