在 Scala 中拥有伴随对象的基本原理是什么?

有没有需要类的伴生对象(单例)的情况?为什么我要创建一个类,比如说 Foo,同时还要为它创建一个伴随对象呢?

38311 次浏览

同伴对象基本上提供了一个可以放置“类静态”方法的地方。此外,伴侣对象或伴侣模块可以完全访问类成员,包括私有成员。

伴随对象非常适合封装工厂方法之类的东西。不必到处使用 FooFooFactory,您可以让一个带有伴生对象的类承担工厂职责。

除了 Saem 在 他的回答中所说的内容,Scala 编译器还在相应的伴随对象(源对象或目标对象)中查找类型的 implicit conversions,因此不需要导入转换。

关于单一对象的原因,Scala 编程说:

正如在第1章中提到的,Scala 比 Java 更面向对象的一个方面是 Scala 中的类不能有静态成员。相反,Scala 有单例对象(p. 65)。

... 并且它是存储伴随类的静态工厂方法(不是那种 DP)的好地方。如果您将这些重载的工厂方法命名为 application (/.../) ,您将能够创建/初始化您的类

  1. 没有“新的”(不是那么重要)

  2. 使用不同可能的参数集(比较 Bloch 在有效 Java 中所写的关于伸缩构造函数的内容)

  3. 能够决定您想要创建哪个派生类,而不是抽象的(附带的)派生类

示例代码:

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

I wouldn't call the object/base class AbstractXxxxx because it doesn't looks bad: like creating something abstract. Give those names a real meaning. Consider using immutable, method less, case classes and seal the abstract base class.

伴随对象用于存储类 but they do not use static方法或字段的所有实例的公共状态和方法。它们使用可以通过继承重写的常规虚方法。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
}

Which produces this output:

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

I always see companion objects as a 舰桥 to write both functional and object oriented code in Scala. Many times we just need pure functions which take some input and provide a processing result. Putting those relevant functions in the companion object makes it easy to look up and use, for myself as well as some one building on top of my code.

此外,它是一种语言提供的功能,可以在不做任何事情的情况下编写单例模式。当您需要一个单例来封装 JVM 生命周期中的委托时,这尤其有用。例如,用 Scala 编写一个简单的 HTTP 客户端库,在这个库中,您可以封装基于 Java 实现的委托,并让 API 的使用者生活在纯粹的世界中。

如果在同一个文件中以相同的名称定义类和对象,它们称为伴类和对象。Scala 没有静态的 JAVA 关键字,你可以用 Scala 中的类和对象代替静态。

更多详细信息请查看文章 Scala 编程中的类和对象关键字

首先,它提供了静态和非静态方法的明确区分。还提供了一种创建单例类的简单方法。

它还可以继承来自其他类和/或 trait 的方法,这是 Java 静态 methods.不能做到的,可以作为参数传递。