是否存在需要类的伴随对象(单例)的情况?为什么我要创建一个类,比如说Foo
并为它创建一个伴生对象?
7 回答
伴随对象基本上提供了一个可以放置“类静态”方法的地方。此外,伴随对象或伴随模块可以完全访问类成员,包括私有成员。
伴随对象非常适合封装工厂方法之类的东西。例如,您可以让一个带有伴随对象的类承担工厂责任,而不是必须在任何地方都有Foo
。FooFactory
伴随对象可用于存储类的所有实例共有的状态和方法,但它们不使用静态方法或字段。他们使用可以通过继承覆盖的常规虚拟方法。Scala 确实没有什么静态的。有很多方法可以使用它,但这里有一个简单的例子。
abstract class AnimalCounter
{
var animals = 0
def name: String
def count()
{
animals += 1
println("%d %ss created so far".format(animals, name))
}
}
abstract class Animal
{
def companion: AnimalCounter
companion.count()
}
object Dog extends AnimalCounter
{
val name = "dog"
}
class Dog extends Animal
{
def companion = Dog
}
object Cat extends AnimalCounter
{
val name = "cat"
}
class Cat extends Animal
{
def companion = Cat
}
产生这个输出:
scala> new Dog
1 dogs created so far
scala> new Cat
1 cats created so far
scala> new Dog
2 dogs created so far
scala> new Cat
2 cats created so far
...并且它是存储伴随类的静态工厂方法(不是那个 DP)的好地方。如果您将那些重载的工厂方法命名为 apply(/ ... /) 您将能够创建/初始化您的类
没有“新”(不是那么重要)
具有不同的可能参数集(与 Bloch 在 Effective Java 中写的关于伸缩构造函数的内容相比)
能够决定您要创建哪个派生类,而不是抽象(伴随的)派生类
示例代码:
abstract class AbstractClass;
class RealThing(s: String) extends AbstractClass;
class AlternativeThing(i: Int) extends AbstractClass;
object AbstractClass {
def apply(s: String) = {
new RealThing(s)
}
def apply(i: Int) = {
new AlternativeThing(i)
}
}
// somewhere else you can
val vs = AbstractClass("asdf") // gives you the RealThing wrapped over string
val vi = AbstractClass(123) // gives you AlternativeThing wrapped over int
我不会调用对象/基类 AbstractXxxxx 因为它看起来不错:就像创建抽象的东西一样。给这些名字一个真正的意义。考虑使用不可变、无方法、案例类并封装抽象基类。
除了 Saem 在他的回复中所说的内容之外,Scala 编译器还在相应的伴随对象(源或目标)中查找类型的隐式转换,因此不需要导入转换。
关于Scala 编程中的单例对象的原因说:
如第 1 章所述,Scala 比 Java 更面向对象的一种方式是 Scala 中的类不能有静态成员。相反,Scala 有单例对象(第 65 页)。
我总是将伴随对象视为在 Scala 中编写函数式代码和面向对象代码的桥梁。很多时候,我们只需要接受一些输入并提供处理结果的纯函数。将这些相关函数放在伴随对象中可以很容易地查找和使用,对我自己以及在我的代码之上构建的一些人来说。
此外,它是一种语言提供的功能,可以在不做任何事情的情况下编写单例模式。当您需要一个单例来为 JVM 的生命周期封装委托者时,这尤其有用。例如,在 Scala 中编写一个简单的 HTTP 客户端库,您可以在其中封装基于 Java 实现的底层委托,并让 API 的使用者生活在纯粹的世界中。
如果您在同一个文件中以相同的名称定义类和对象,则它们称为伴生类和对象。Scala 没有 static 作为 JAVA 关键字,您可以将静态替换为 Scala 中的伴随类和对象。
有关更多详细信息,请查看 Scala 编程中的文章类和对象关键字
首先,它提供了静态与非静态方法方法的清晰分离。还提供了一种创建单例类的简单方法。
它还可以从其他类和/或特征继承方法,这是 Java 静态方法无法做到的。并且可以作为参数传递。