为什么静态方法不被认为是良好的OO实践?

时间:2010-10-23 02:46:25

标签: java scala oop static-methods language-concepts

我正在阅读Programming Scala。在第4章的开头,作者评论说Java支持静态方法,这些方法是“不那么纯粹的OO概念”。为什么会这样?

7 个答案:

答案 0 :(得分:59)

面向对象有三件事:

  • 消息,
  • 本地保留和保护以及隐藏状态进程,
  • 所有事情的极端后期约束。

在这三个中,最重要的一个是消息

静态方法至少违反了消息传递和后期绑定。

消息传递的概念意味着在OO中,计算由自包含对象的网络执行,这些对象向对方发送消息。发送消息是唯一的通信/计算方式。

静态方法不这样做。它们与任何对象无关。根据通常的定义,它们实际上不是所有方法。他们真的只是程序。 Java静态方法Foo.bar和BASIC子例程FOO_BAR之间几乎没有区别。

至于后期绑定:更现代的名称是动态调度。静态方法也违反了这一点,事实上,它甚至以它们的名字命名: static 方法。

静态方法打破了面向对象的一些非常好的属性。例如,面向对象的系统在对象充当功能时自动具有功能安全性。静态方法(或者实际上任何静态,是静态或静态方法)会破坏该属性。

您也可以在自己的进程中并行执行每个对象,因为它们只通过消息进行通信,从而提供一些简单的并发性。 (就像 Actors ,基本上,这不应该太令人惊讶,因为Carl Hewitt创建了基于Smalltalk-71的Actor模型,而Alan Kay创建的Smalltalk-71部分基于PLANNER,而后者则是由Carl Hewitt创建。演员和对象之间的密切关系远非巧合,事实上,它们基本上是同一个。)同样,静态(静态方法,以及尤其是静态)打破那个不错的财产。

答案 1 :(得分:30)

不要将“不那么纯粹的OO概念”与“不良做法”混为一谈。作为“纯粹的OO”并不是你应该尝试实现的灵丹妙药。仅仅因为静态方法不将实例变量作为参数并不意味着它们没有用处。有些事情本身并不适用于物体,为了“纯洁”,它们不应该被迫进入那种模具。

有些人认为事情应该是“纯粹的”,因此任何“不纯”都是不好的做法。实际上,糟糕的做法只是做一些令人困惑,难以维护,难以使用的事情等。创建带有实例的静态方法是不好的做法因为任何采用实例的方法都应该是实例方法。另一方面,实用程序和工厂函数之类的东西通常不会占用实例,所以它们应该是静态的。

如果你想知道他们为什么不是“纯粹的OO”,那是因为它们不是实例方法。 “纯粹的”OO语言将所有东西都作为对象,所有函数都是实例方法。当然,这并不是一直非常有用。例如,考虑Math.atan2方法。它需要两个数字,不需要任何状态。您甚至可以将它作为方法的哪个对象?在“纯”OO语言中,Math本身可能是一个对象(可能是单例),而atan2将是一个实例方法,但由于该函数实际上并未使用任何状态, Math对象,它也不是“纯粹的OO”概念。

答案 2 :(得分:25)

迄今为止尚未提及的静态方法不是非常OO的一个原因是接口和抽象类只定义了非静态方法。因此静态方法不适合继承。

另请注意,静态方法无法访问“super”,这意味着无法在任何真实意义上覆盖静态方法。实际上,它们根本无法被覆盖,只能被隐藏。试试这个:

public class Test {
    public static int returnValue() {
        return 0;
    }

    public static void main(String[] arg) {
        System.out.println(Test.returnValue());
        System.out.println(Test2.returnValue());
        Test x = new Test2();
        System.out.println(x.returnValue());
    }
}


public class Test2 extends Test {
    public static int returnValue() {
        return 1;
    }
}

当你运行它时,你将得不到你所期望的。 Test.returnValue()给出了您的期望。 Test2.returnValue() 隐藏超类中同名的方法(它不会覆盖它),它会提供您所期望的内容。

有人可能天真地期望“非静态地”调用静态方法来使用多态。它没有。声明变量的类是用于查找方法的类。这是一种糟糕的形式,因为有人可能希望代码能够做与实际不同的事情。

这并不意味着“不要使用静态方法!”它确实意味着您应该为那些您真正希望Class对象拥有该方法的实例保留静态方法的使用,而不仅仅是作为单个实例的懒惰方式。

答案 3 :(得分:7)

静态方法导致紧耦合,这违反了良好的面向对象设计。由于静态方法固有地不支持面向对象的设计技术,如继承和多态,因此无法通过依赖性反转来避免调用代码与静态方法中的代码的紧密耦合。

除了静态方法很难测试因为这些紧密耦合的依赖关系,这通常会导致代码依赖的第三方基础结构 - 比如数据库,并且很难在不实际进入的情况下更改行为并改变代码。

答案 4 :(得分:3)

由于以下原因,静态方法不被视为良好的OO实践:

1)防止可重复使用:

无法覆盖静态方法。它不能用于界面。

2)对象的生命周期很长:

静态方法在内存中保留一段日志时间,其垃圾回收需要很长时间。开发人员无法控制销毁或创建静态变量。 过度使用静态变量会导致内存溢出。

3)此外,还有其他一些观点:

它不尊重封装,因为对象不会完全控制其状态。它不遵循控制反转,松散耦合,依赖注入等概念。

答案 5 :(得分:1)

静态方法不是那么纯粹的OO概念,因为可以在没有实际与它们关联的对象的情况下调用它们。你使用这个类本身。您可以像Classname.method(...);

一样调用它们

答案 6 :(得分:0)

OO的概念是关于控制/访问来自对象的数据,但静态方法不需要使用对象来调用,它们属于类而不是对象。

- 干杯