【问题标题】:Why best practices vary for Static classes in OOP?为什么 OOP 中静态类的最佳实践各不相同?
【发布时间】:2014-10-26 08:35:15
【问题描述】:

我目前正在阅读有关 Java 最佳实践的信息,我发现根据 this book,我们必须优先考虑静态类而不是非静态类。我记得在 C# 最佳实践中,我们必须根据 Dennis Doomen 的 C# 3.0、4.0 和 5.0 编码指南避免这种情况:

AV1008 - 避免静态类

除了扩展方法容器之外,静态类通常会导致代码设计不良。除非您愿意使用一些非常 hacky 的工具,否则它们也很难(如果不是不可能的话)单独测试。注意如果您确实需要该静态类,请将其标记为静态,以便编译器可以阻止实例成员和实例化您的类。这使您不必创建显式的私有构造函数。

我发现这两个用于 C# answerJava answer 何时使用和避免使用静态类,但只是出于好奇 - C# 和 Java 都是 OOP 语言,为什么在最佳实践中会有这么大的差异?

更新: 我无法从 Java 书中复制这么多页面,但底线是:

如果您声明的成员类不需要访问 封闭 例如,总是将静态修饰符放在其声明中,使其成为静态的 而不是一个非静态成员类。如果你省略这个修饰符,每个实例都会 对其封闭实例有一个无关的引用。存储此参考成本 时间和空间,并且可能导致封闭实例在 否则将有资格进行垃圾收集(第 6 项)。如果你曾经 需要分配一个没有封闭实例的实例,你将无法做到 因此,作为非静态成员类实例需要有一个封闭实例。 私有静态成员类的一个常见用途是表示 由它们的封闭类表示的对象。

那么仅与性能有关吗?

注意,这个问题更多的是关于静态类和 OOP,而不是 Java 和 C# 之间的差异。

【问题讨论】:

  • 那本书的作者有没有说明为什么我们应该偏爱静态类而不是非静态类
  • 我也一直在想关于 Python 的问题。Pycharm(python 的一个 ide)在我的代码中充斥着警告说方法可以设为静态,这让我发疯
  • 不是此类问题的正确论坛。
  • 我认为您缺少书中的上下文,您必须给出摘录形式的书来判断。
  • C#和Java中的静态类有一个根本的区别,虽然它们使用相同的关键字,但它们是不一样的概念。

标签: java c# oop static


【解决方案1】:
  1. 我认为第二个文本片段是关于 member classenclosing,这是 Java 特有的功能(它是如何实现的)。
  2. 静态类或字段(如在 C# 中)实际上是不好的设计实践 - 看看 OOP 和 SOLID。此外,它可能会导致 CLR 级别的一些性能问题。但是私有静态方法并没有错。我记得,Resharper 建议让私有方法独立于具体实例静态。它增加了可读性并且没有副作用。而且您不需要对私有方法进行单元测试。这也是不好的做法。
  3. 最后,一些作者简要介绍了技术,而另一些作者则写了一些关于设计原则的文章。这些观点之间经常存在矛盾(但描绘的两个片段与此无关)。

【讨论】:

    【解决方案2】:

    JoshuaBloch 提供的建议也适用于 c#,而为 c# 提供的建议也适用于 java(在某种程度上,他们谈论的是静态类)。

    为什么要使用静态成员?

    • 他们不需要实例来调用他们
    • 在c#中,他们使用call opcode,它不需要检查null(这是一个微优化),而不是实例方法(使用callvirt opcode)。我相信类似的东西也会出现在 java 中。
    • 如果不使用实例,它们不会阻止 GC。
    • 也没有将this 引用传递给所有隐藏方法的开销。

    如果您习惯于 Resharper Visual Studio 的生产力工具,它将给出与 JoshuaBloch 为 java 给出的建议相同的建议,在 c# 中说 Method can be made static 在给定的链接中是合理的.

    为什么不使用静态成员?

    • 它们是不可测试的(很容易)。
    • 他们无法实现接口成员。
    • 它们不能通过依赖注入来注入。
    • 它们不参与多态性(这在面向对象的语言中非常需要)。
    • 在 C# 中,静态类不能作为引用传递。

    因此,如果您理解它们并且它们适用于两种语言,那么这两个建议都很好。在合适的时候使用它们,在不合适的时候避免它们。

    【讨论】:

    • 最好使用静态类而不是单例。大多数静态类也可以成为线程安全的。
    • @Aniket 我不明白。为什么这样?静态不会使固有的线程安全。我们需要为线程安全付出代价。单例类也必须是线程安全的。
    • 可以..不是他们默认是
    • 我的意思是说它们可以成为线程安全的单例。
    • @Aniket,真的吗?经典的单例实现对类客户端是透明的,静态的 - 不是。一旦你将某个类设为静态,你就会拒绝所有 OOP 的好处,因为至少(!)静态类不能被派生或继承。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多