我突然想知道为什么我们有非静态函数/方法?方法不是对象的属性(如属性/数据成员),并且该类的所有实例都使用相同的方法,那么为什么静态和非静态方法之间存在差异?这是否意味着当对象被实例化时,它会保存方法的副本 - 这对于该类的所有实例都完全相同?
编辑:所有负面因素是什么?我的观点是有效的 - 方法的行为不会改变每个对象的实例。对于每个对象,该方法都是相同的,只是一个不同的对象调用该方法,那么为什么我们需要使该方法成为该对象的一部分?为什么这个方法不能只存储一次(比如静态方法)然后当使用“this”时我们就执行相关的对象?对于每个实例,存储非静态方法都是对象的一部分似乎很愚蠢。
答案 0 :(得分:5)
静态方法通常不依赖于或改变对象的状态。非静态方法通常会这样做。
至于方法代码是否包含在对象的每个实例中,不是,它不是。
基本上每个方法都定义一次,然后this
作为参数静默传递。有点过于简单化了,但希望能有所了解。
答案 1 :(得分:3)
这样我们就可以在方法中使用this
关键字..简单。它属于那个特定的实例
答案 2 :(得分:1)
非静态方法可以访问实例的数据(属性/属性)。静态方法不能因为它们不属于该类的实例。这是面向对象编程的要点。您正在封装数据和适用于该数据的功能..
答案 3 :(得分:1)
非静态方法不属于像字段那样的类的实例。非静态方法只是意味着它可以访问实例字段。就副本而言,只有一个副本,而不是每个对象有一个副本的字段。
现在在具有功能支持的OO语言中,方法可以是对象的字段,但这完全不同。
答案 4 :(得分:1)
在类的特定实例上调用非静态方法。在没有实例的情况下调用静态方法,即使没有该类的实例,也可以运行。
实例实际上并不包含方法代码的单独副本,但仅仅因为存储相同内容的重复副本没有意义。您可以将非静态方法视为属于实例而不是类。
答案 5 :(得分:1)
静态函数与对象的实例无关。成员函数是this
关键字的来源;编译器将其作为隐藏参数传递给成员函数,但不传递给静态函数。
答案 6 :(得分:1)
OOP的一个关键思想是保持数据接近在其上运行的代码。非静态方法使您能够这样做:您可以定义与一组属性紧密相关的功能,以便您的类的用户(这些属性的属性和功能的组合)可以关注功能而不是数据本身。
答案 7 :(得分:1)
好的,让我们看看......
我突然想知道为什么我们有非静态函数/方法?方法不是对象的属性(如属性/数据成员),并且该类的所有实例都使用相同的方法,那么为什么静态和非静态方法之间存在差异?
需要注意的关键是概念差异。 实例方法在调用时与特定对象“关联” - 它具有某种形式的“this”上下文 - 而静态方法< / em>不是。
这是否意味着当一个对象被实例化时,它会保存一个方法的副本 - 这对于该类的所有实例都完全相同?
这取决于语言,但通常没有。
例如,在Java中,只为该类的所有实例共享一个方法的副本。对于类的实例,方法不是数据的“部分”。在JavaScript中,可以通过使用[[prototype]]链来获得此共享,或者在较小程度上,通过在不同实例中重用相同方法的相同函数对象。 (但是,也可以为JavaScript中的每个 new 实例创建 new 方法,但这是程序员的选择。)
在Java中,发送“消息”以调用实例方法;也就是说,它查看特定的类型并将消息与适当的“this”实例一起发送给它。 (由于虚拟调度,这比这更复杂,但是......需要注意的是,只有一个特定类型的方法副本被加载到内存中。)
在JavaScript中,方法是第一类值(它是一个对象),它是通过对象的属性命名的(或者在[[prototype]中找到]])动态绑定到接收器(也就是说,“this”内部是基于如何调用建立的)。 Python与JavaScript类似,因为方法是第一类函数,它们被提取和调用(但方法仍然“绑定”到类,这与JavaScript不同)。 Ruby更像Java,因为“发送消息”反过来调用一个方法(不是 Ruby中的第一类值)并隐式地将上下文与接收者相关联。所有这些语言都支持各种形式的“子类化”(可以称之为),以调整MRO并共享实例共有的方法。
该方法对于每个对象都是相同的,只是一个不同的对象调用该方法,那么为什么我们需要使该方法成为该对象的一部分?为什么这个方法不能只存储一次(比如静态方法)然后当使用“this”时我们就执行相关的对象?对于每个实例,存储非静态方法都是对象的一部分似乎很愚蠢。
这就是许多语言所做的 - 包括Java,C ++,Python(通常)和Ruby(通常)和JavaScript(通常),它是非常有效的点,可以节省内存和开销
快乐的编码!