在 Scala 中拥有伴生对象的基本原理是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/609744/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the rationale behind having companion objects in Scala?
提问by Rahul
Is there a case where a companion object (singleton) for a class is needed? Why would I want to create a class, say Fooand also create a companion object for it?
是否存在需要类的伴随对象(单例)的情况?为什么我要创建一个类,比如说Foo并为它创建一个伴生对象?
采纳答案by Saem
The companion object basically provides a place where one can put "static-like" methods. Furthermore, a companion object, or companion module, has full access to the class members, including private ones.
伴生对象基本上提供了一个可以放置“类静态”方法的地方。此外,伴生对象或伴生模块可以完全访问类成员,包括私有成员。
Companion objects are great for encapsulating things like factory methods. Instead of having to have, for example, Fooand FooFactoryeverywhere, you can have a class with a companion object take on the factory responsibilities.
伴随对象非常适合封装工厂方法之类的东西。而不必有,例如,Foo和FooFactory无处不在,你可以有一个伴侣对象采取在工厂责任的一类。
回答by Craig P. Motlin
Companion objects are useful for storing state and methods that are common to all instances of a class but they do not use staticmethods or fields. They use regular virtual methods which can be overridden through inheritance. Scala truly has nothing static. There are lots of ways you can use this but here's a simple example.
伴随对象可用于存储类的所有实例通用的状态和方法,但它们不使用静态方法或字段。它们使用可以通过继承覆盖的常规虚拟方法。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
回答by Szymon Jachim
...and it's a good place to store static factory methods (not that DP) for accompanied classes. If you name those overloaded factory methods apply(/.../) you will be able to create/initialize you class
...它是为伴随类存储静态工厂方法(不是那个 DP)的好地方。如果您将那些重载的工厂方法命名为 apply(/ .../) 您将能够创建/初始化您的类
without 'new' (not really that important)
with different possible sets of parameters (compare to what Bloch writes in Effective Java about telescoping constructor)
with the ability to to decide which derived class you want to create instead of the abstract (accompanied) one
没有“新”(不是那么重要)
使用不同的可能参数集(与 Bloch 在 Effective Java 中关于伸缩构造函数的内容相比)
能够决定要创建哪个派生类而不是抽象(伴随)类
Example code:
示例代码:
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.
我不会调用对象/基类 AbstractXxxxx 因为它看起来不错:就像创建抽象的东西一样。赋予这些名字真正的意义。考虑使用不可变的、方法较少的、案例类并密封抽象基类。
回答by Fabian Steeg
In addition to the things Saem said in his reply, the Scala compiler also looks for implicit conversionsof types in the corresponding companion objects (of either the source or the target), so the conversions don't need to be imported.
除了 Saem 在他的回复中所说的内容之外,Scala 编译器还会在相应的伴生对象(源或目标)中查找类型的隐式转换,因此不需要导入这些转换。
About the reason for singleton objects in general Programming in Scalasays:
As mentioned in Chapter 1, one way in which Scala is more object-oriented than Java is that classes in Scala cannot have static members. Instead, Scala has singleton objects (p. 65).
正如在第 1 章中提到的,Scala 比 Java 更面向对象的一种方式是 Scala 中的类不能有静态成员。相反,Scala 有单例对象(第 65 页)。
回答by Gaurav Abbi
I always see companion objects as a bridgeto 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.
我总是将伴生对象视为在 Scala 中编写函数式和面向对象代码的桥梁。很多时候我们只需要接受一些输入并提供处理结果的纯函数。将这些相关的函数放在伴随对象中可以很容易地查找和使用,对于我自己以及构建在我的代码之上的某个人来说。
Moreover, it is a language provided feature to write the singleton pattern without doing anything. This is especially useful when you need a singleton to encapsulate a delegator for the life of JVM. For example, writing a simple HTTP client library in Scala where you can encapsulate an underlying Java implementation based delegator and let consumers of your API live in pure world.
此外,它是一种语言提供的功能,可以在不做任何事情的情况下编写单例模式。当您需要单例来封装 JVM 生命周期的委托时,这尤其有用。例如,在 Scala 中编写一个简单的 HTTP 客户端库,您可以在其中封装一个基于 Java 实现的底层委托器,让您的 API 的使用者生活在纯粹的世界中。
回答by FOD
If you define class and object in same file with same name, they known as companion class and object. Scala don't have static as JAVA keyword, You can take as replacement of static with companion class and object in Scala.
如果您在同一个文件中定义了同名的类和对象,则它们称为伴生类和对象。Scala 没有 static 作为 JAVA 关键字,您可以将 static 替换为 Scala 中的伴随类和对象。
For more detail information please check article class and object keyword in scala programming
有关更多详细信息,请查看scala 编程中的文章 类和对象关键字
回答by vipin
At first, it provides a clear separation of static vs non static methods methods.Also provide a simple way to create singleton class.
首先,它明确区分了静态方法和非静态方法。还提供了一种创建单例类的简单方法。
It also can inherit methods from other classes and/or traits, which cannot be done with Java static methods.and can be passed as a parameter.
它还可以从其他类和/或特征继承方法,这是 Java 静态方法无法完成的。并且可以作为参数传递。

