纯方法必须是静态的吗?

Does a pure method have to be static?

我目前正在研究一本教科书,它将纯方法定义为:

"a static method that depends only on its parameters and no other data"

难道实例方法不是静态的就可以是纯方法吗(只要不修改参数,没有'side-effects'之类的打印)?

我知道纯方法是纯方法,return 值仅取决于参数而不取决于任何其他状态,因此调用实例方法的方式可能意味着从调用该方法的对象不算作参数,而是另一个 "state"?

除此之外,我想不出非静态方法不能成为纯方法的任何原因。

这是一个例子:

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;
    }
}

上面定义了一个Rationalclass

然后您可以在 Rational class 中编写一个方法,其中 return 是一个 Rational 对象作为 double 通过 'Method one'或下面的 'Method two'。

方法一:

public double toDouble() {
    double x = this.numer;
    double y = this.denom;
    double fprat = x / y;
    return fprat;
}   

方法二:

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

它们本质上做的是完全相同的事情,但一个是静态方法,另一个是实例方法,因此它们的调用将采用不同的格式。方法二当然是纯方法,但是非静态的方法一在这种情况下也可以定义为纯方法吗?

"Pure" 基本上就是 "depends only on its arguments and has no side-effects"。

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

因此 "static" 和 "instance" 的概念与 "pure" 的概念没有直接关系。

纯方法 也可能是 静态的。纯方法的两个标准是,according to Wikipedia:

  1. The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.

  2. Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.

(强调我的)

没有理由不能将其应用于非静态方法。使方法静态化会给调用者更强的保证,即没有使用实例状态,因此最好将其静态化。


根据您的观点,可以将实例方法视为一个简单的函数,它带有一个额外的隐式参数:实例本身。通过这种方式,非静态方法可以依赖实例状态并被认为是纯方法,前提是它不依赖任何外部状态(单例等)或产生副作用。 。这取决于解释,但我个人认为这样的方法是纯粹的。

Voo 在评论中写得很好:

Why should a hidden this pointer be considered any more special than any other parameter to the function? That argument leads to a contradiction: Assume that
public static int pureFunc(MyInstance self) is pure, clearly the isomorph
public int pureFunc() would be pure as well.

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

另一方面,从技术上讲,您也可以将实例方法视为具有第零个参数(对象本身)的静态方法。如果该对象是 immmutable(或者该方法不会更改对象中的任何内容),您可以争辩说该方法仍然是纯方法。基本上,您将 "object" 视为附加参数。

例如

Method references in Java 可以这样做,使第一个参数成为调用方法的对象本身。

这个方法:

public int add(int a, int b) {
   return a + b;
}

不是静态的,但它的 return 值不依赖于参数以外的任何东西。但正因为如此,add 根本不需要是实例方法!

我认为这就是您的教科书所要表达的意思 - 不访问状态或改变状态的实例方法也可能是静态的。

实例方法应该依赖于对象的状态,否则应该是静态方法。并且不依赖于静态的静态方法是纯的。

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

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

这里的问题可能与 static 阻止的虚拟调度有关。基础 class 方法可能是纯的,而派生的 class 方法可能是不纯的,而它们在 Java 类型系统中的约定是相等的。

不能保证 static 方法是 pure。从技术上讲,静态方法可以具有静态。 这就是为什么你的假设

"a static method that depends only on its parameters and no other data"

不正确。

编辑 在 Bergi 评论后

正如我之前所说,static 关键字并不能保证无状态。 如果您在引用中省略 static 关键字,它仍然是正确的。

所以回答你的问题。纯方法必须是静态的吗?答案是视情况而定。

将纯函数设为静态有好处,即:

  • 这是一种自我检查,保证您不会(意外地)更改 class;

  • 中的状态
  • 无法覆盖该方法。这保证该方法将来不会改变状态。

但另一方面,模拟静态方法很困难,在测试过程中可能会出现问题。