纯方法必须是静态的吗?

Jos*_*man 28 java semantics

我现在正在编写一本教科书,它将纯方法定义为:

"一种静态方法,仅取决于其参数而不依赖于其他数据"

如果一个实例方法不是静态的(只要它不修改参数并且没有像打印那样的"副作用"),那么它是不可能的?

我知道纯方法是纯粹的,返回值只取决于参数而不依赖于任何其他状态,所以可能调用实例方法意味着从调用方法的对象中获取的变量不算作参数但作为另一个"状态"?

除此之外,我无法想到为什么非静态方法不能成为纯方法.

这是一个例子:

public class Rational {

    private int numer;
    private int denom;

    public Rational() {
        this.numer = 0;
        this.denom = 1;
    }

    public Rational(int numer, int denom) {
        this.numer = numer;
        this.denom = denom;
    }
}
Run Code Online (Sandbox Code Playgroud)

以上定义了一个Rational

然后,您可以在Rational类中编写一个方法,该方法通过下面的"方法一"或"方法二" 返回一个Rational对象double.

方法一:

public double toDouble() {
    double x = this.numer;
    double y = this.denom;
    double fprat = x / y;
    return fprat;
}   
Run Code Online (Sandbox Code Playgroud)

方法二:

public static double toDouble(Rational rational)
{
    double x = rational.numer;
    double y = rational.denom;
    double fprat = x / y;
    return fprat;
} 
Run Code Online (Sandbox Code Playgroud)

它们基本上完全相同,但一个是静态方法,另一个是实例方法,因此它们的调用方式不同.方法二肯定是纯方法,但是方法一,非静态,在这些情况下也被定义为纯方法?

Rob*_*gam 28

该定义的"静态"部分是多余的.静态方法不保证它不依赖于任何其他状态.我怀疑定义只是想确保该方法不使用实例变量.

另一方面,从技术上讲,您也可以将实例方法视为具有第零个参数的静态方法,即对象本身.如果该对象是不可变的(或者该方法不会改变对象中的任何内容),那么您可能会认为该方法仍然是纯粹的.基本上您将"对象"视为附加参数.

例如,Java中的方法引用可以以这种方式运行,使第一个参数成为调用该方法的对象本身.

  • 可以辩论?*应该*争论. (5认同)
  • @Bergi同意.我没有太多理由认为传递给实例的`this`参数比任何其他参数更特殊.或者,如果隐藏参数确实改变了含义 - 为什么传递给静态方法的隐藏类指针也不是问题?它没有多大意义. (4认同)
  • 我认为第2段中的可变性并不重要.只应该比两个相等的实例(`a == b`)产生相同的结果`af(x)== bf(x)`(并且没有副作用) (3认同)
  • @RobertBräutigam如果您将实例视为函数的隐式参数,那么如果实例在调用之间发生更改,那么您不会使用与之前相同的参数调用该方法.因此,它仍然可以是纯粹的并且是可变的. (2认同)

Mic*_*ael 22

纯方法也可能是静态的.根据维基百科的说法,纯方法的两个标准是:

  1. 在给定相同参数值的情况下,该函数始终评估相同的结果值.所述函数的结果值可以不依赖于任何隐藏的信息状态,其可以同时执行程序进行变更或程序的不同执行之间,也不能依赖于从I/O设备的任何外部输入.

  2. 对结果的评估不会导致任何语义上可观察到的副作用或输出,例如可变对象的突变或输出到I/O设备.

(强调我的)

没有理由不适用于非静态方法.使方法成为静态会给调用者提供更强的保证,即不使用任何实例状态,因此最好将其设置为静态.


根据您的观点,可以将实例方法视为仅采用额外隐式参数的函数:实例本身.通过这种方式,非静态方法可以依赖于实例状态并被认为是纯粹的,只要它不依赖于任何外部状态(单例等)或产生副作用.罗伯特的回答很好.这取决于解释,但我的观点是这种方法是纯粹的.

Voo在评论中说得很好:

为什么隐藏的this指针应该被认为比函数的任何其他参数更特殊?这个论点导致了一个矛盾:假设这
public static int pureFunc(MyInstance self) 是纯粹的,显然同构
public int pureFunc()也是纯粹的.

  • 这似乎依赖于许多语言隐藏传递给实例方法的this指针这一事实.但是忽略了这个约定我不明白为什么应该处理一个`this`指针而不是该方法的任何其他输入.实际上,通过该定义,只要方法不改变它们,访问成员变量也是完全正确的! (5认同)
  • @Bakuriu我会说这取决于解释.如果我们说在实例上调用函数与调用具有该对象的函数作为隐式参数相同,我认为在状态改变后调用相同的函数是**不**调用该函数与"相同的参数值". (3认同)

Zde*_*nek 11

从概念上讲,静态方法和实例方法之间的唯一区别是实例方法具有可通过this关键字访问的隐藏参数.

因此,this如果它不符合纯静态方法的条件,那么不变异的实例方法就是纯粹的.

这里的问题可能与虚拟调度相关,而虚拟调度则受到阻止static.基类方法可能是纯粹的,而派生类方法可能是不纯的,而它们在Java类型系统中的契约是相等的.


Mal*_*alt 5

"纯粹"基本上意味着"仅取决于其论点并且没有副作用".

静态方法不必是纯粹的,因为它可能访问静态数据结构.同样,实例方法可能是纯粹的,因为它不访问任何实例变量.

因此,"静态"和"实例"的概念与"纯粹"的概念没有直接关系.