如果单身汉如此糟糕,为什么Scala对他们有语言支持?

如果单身汉如此糟糕,为什么Scala对他们有语言支持?,scala,object,static,singleton,anti-patterns,Scala,Object,Static,Singleton,Anti Patterns,可能重复: 为什么Scala对单例反模式有语言支持?如果Scala从Java继承了静态关键字,那么对象关键字的合法用例会剩下什么呢?至少有一个预先的区别,Scala中的对象实际上是一个对象(即实例),而不是Java中的对象,它只是类本身调用的方法 这意味着它避免了关于单例的主要抱怨之一——因为它是一个实例,它可以被传递并连接到方法中,因此可以在测试期间交换到其他实现中,等等。如果有什么不同的话,它是单例的推荐替代方案的语法糖——有一个带有getInstance()的类方法返回默认的单个实例 这

可能重复:


为什么Scala对单例反模式有语言支持?如果Scala从Java继承了
静态
关键字,那么
对象
关键字的合法用例会剩下什么呢?

至少有一个预先的区别,Scala中的
对象
实际上是一个对象(即实例),而不是Java中的对象,它只是类本身调用的方法

这意味着它避免了关于单例的主要抱怨之一——因为它是一个实例,它可以被传递并连接到方法中,因此可以在测试期间交换到其他实现中,等等。如果有什么不同的话,它是单例的推荐替代方案的语法糖——有一个带有
getInstance()的类
方法返回默认的单个实例

这样说,我认为单体反模式更多的是设计,而不是语言特征。如果你构造你的代码库,使得一些单一的依赖关系隐式地连接到大多数类中,那么你在改变它时就会遇到问题——不管语言特性如何


Scala中存在
对象
的合法用例(例如,将
案例对象
用于,或将多个
密封特征
扩展为一个)。语言特性可能被滥用,但在我看来,它不如Java的
静态
,更有用。

没有状态的单例并没有那么糟糕。我将对象(在scala中)视为将函数(行为)放入其中的模块

例如类型类。静态类和单例的区别在于,单例是对象,可以作为参数传递。例如,此代码无法使用静态类生成:

trait TypeClass[A] {
  def method(x: A): A
}

implicit object IntTypeClass extends TypeClass[Int] {
  def method(x: Int) = x*x
}

def foo[A](x: A)(implicit tc: TypeClass[A]) = tc.method(x)

scala> foo(2)
res0: Int = 4

如果您使用一个对象来保存状态,那么单例就是一个灾难,因为可能没有办法清除它,这是单例作为反模式的主要示例之一。没有可变状态且具有纯函数的对象在这方面不太容易造成痛苦,下面是一个示例:

object StringSerializer extends Serializer[String] {
  // Implementation goes here.
}

在这种情况下,不需要重新创建序列化程序实例,这样可以简化代码并提高性能。

我不会说单例真的很糟糕,只是它们在大多数情况下被误用并成为反模式。也就是说,我从未遇到过静态类不能更好地工作的情况。静态声明本质上只是全局变量,比单例声明更为广泛地受到谴责。单例可以以同样的方式被误用,但至少可以从接口中继承,隐藏在接口后面,并提供静态调用所不具备的可测试性和代码解耦的潜力。有适当的地方可以使用单例。例如,如果系统具有一个资源,而该资源一次只能由一个调用者安全地进行交互,那么为该资源使用单例包装器可能是有意义的。例如,一个STDOUT流对象可以被建模为一个单例,如果其他的类B有使用其中一个单例的方法C,并且你想用mock而不是真正的单例方法对方法C进行单元测试,那么你会怎么做?