纯方法必须是静态的吗?

时间:2018-05-22 11:12:35

标签: java semantics

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

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

如果实例方法不是静态的(只要它不修改参数并且不会产生副作用),那么实例方法是不可能的。喜欢印刷)?

我知道纯方法是纯的,返回值只取决于参数而不取决于任何其他状态,因此可能调用实例方法意味着从调用方法的对象中获取的变量不需要&# 39; t计为参数,但作为另一个"状态"?

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

以下是一个例子:

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

以上定义了Rational

然后,您可以在Rational类中编写一个方法,该方法将Rational对象作为double返回“方法一”'或者'方法二'下方。

方法一:

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

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

6 个答案:

答案 0 :(得分:28)

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

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

例如,Java中的

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

答案 1 :(得分:21)

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

  
      
  1. 该函数始终评估相同的结果值   参数值。 功能结果值不能依赖于任何   程序执行时可能发生变化的隐藏信息状态   继续或在程序的不同执行之间,也不是   取决于I / O设备的任何外部输入。

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

  4.   

(强调我的)

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

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

Voo在评论中说得很好:

  

为什么隐藏的这个指针应该被认为是比它更特殊   函数的任何其他参数?这个论点导致了一个   矛盾:假设
  public static int pureFunc(MyInstance self)   是纯净的,显然是同形体   public int pureFunc()会纯洁的   好。

答案 2 :(得分:11)

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

因此,不改变this的实例方法是纯粹的,否则它将有资格作为纯静态方法。

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

答案 3 :(得分:5)

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

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

所以“静态”和“实例”的概念与“纯粹”的概念没有直接关系。

答案 4 :(得分:1)

此方法:

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

不是静态的,但其返回值不依赖于除参数之外的任何内容。但正因为如此,add根本不需要是实例方法!

我认为这是你的教科书所得到的 - 不访问状态或改变状态的实例方法也可能是静态的。

实例方法假设依赖于对象的状态,否则它应该是静态方法。不依赖静态的静态方法是纯粹的。

答案 5 :(得分:0)

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

的原因
  

“仅依赖于其参数且不依赖于其他数据的静态方法”

不是真的。

修改 在Bergi评论之后

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

回答你的问题。纯方法必须是静态的吗?答案取决于它。

使纯函数静态有一些好处,即:

  • 这是一种自我检查,保证你不会(意外)改变你班级的状态;

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

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