在Scala中使用伴随对象的理由是什么?

时间:2009-03-04 08:46:41

标签: oop scala companion-object

是否需要一个类的伴侣对象(单例)?为什么我要创建一个类,比如说Foo并为它创建一个伴随对象?

7 个答案:

答案 0 :(得分:73)

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

Companion对象非常适合封装工厂方法之类的东西。例如,无需在任何地方拥有FooFooFactory,您可以让一个带有伴侣对象的班级承担工厂责任。

答案 1 :(得分:60)

伴随对象对于存储类的所有实例共有的状态和方法非常有用,但它们不使用静态方法或字段。它们使用常规虚拟方法,可以通过继承覆盖它们。 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

答案 2 :(得分:30)

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

  1. 没有'新'(不是那么重要)

  2. 使用不同的可能参数集(与Bloch在Effective Java中关于伸缩构造函数的内容相比)

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

  4. 示例代码:

    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,因为它看起来并不坏:就像创建一些抽象的东西一样。给这些名字一个真正的意义。 考虑使用不可变的,方法较少的case类并密封抽象基类。

答案 3 :(得分:19)

除了Saem在his reply中所说的内容之外,Scala编译器还会在相应的伴随对象(源或目标)中查找implicit conversions个类型,因此转换不会需要进口。

关于单身对象的一般原因Programming in Scala说:

  

如第1章所述,Scala比Java更面向对象的一种方式是Scala中的类不能有静态成员。相反,Scala具有单例对象(第65页)。

答案 4 :(得分:3)

我总是将伴侣对象视为 bridge ,以在Scala中编写功能和面向对象的代码。很多时候我们只需要纯函数来获取一些输入并提供处理结果。将这些相关的函数放在伴随对象中可以让我自己以及在我的代码之上构建一些建筑物时,可以轻松查找和使用它们。

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

答案 5 :(得分:0)

如果在具有相同名称的同一文件中定义类和对象,则称为伴随类和对象。 Scala不具有静态的JAVA关键字,您可以将Scala中的伴随类和对象替换为static。

有关详细信息,请查看文章 class and object keyword in scala programming

答案 6 :(得分:-1)

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

它也可以继承其他类和/或特征的方法,这些方法不能用Java静态方法完成。并且可以作为参数传递。