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


Answers:


82

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

伴侣对象非常适合封装工厂方法之类的东西。而不必有,例如,FooFooFactory无处不在,你可以有一个伴侣对象采取在工厂责任的一类。


61

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

1
类似的插图也可以在这里找到:daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik 2012年

30

...这是一个为伴随的类存储静态工厂方法(不是DP)的好地方。如果您将那些重载的工厂方法命名为apply(/ ... /),则可以创建/初始化您的类

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

  2. 具有不同的可能参数集(与Bloch在Effective 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

我不会调用对象/基类AbstractXxxxx,因为它看起来并不糟糕:就像创建抽象的东西一样。给那些名字一个真实的含义。考虑使用不可变,较少方法的案例类,并密封抽象基类。


2
RealThingAlternativeThing类应具有一个private构造函数,以强制用户使用AbstractClasshas工厂。class AlternativeThing private(i: Int) extends AbstractClass
2014年

@ [Szymon Jachim] Scala抽象类不支持多重继承。那么,为什么编译器允许您使用它呢?
user2441441


3

我总是把伴侣当作桥梁在Scala中编写功能代码和面向对象代码。很多时候,我们只需要纯函数即可接受一些输入并提供处理结果。将这些相关函数放在伴随对象中,对于我自己以及在我的代码之上的一个建筑物而言,都易于查找和使用。

此外,它是一种语言提供的功能,无需执行任何操作即可编写单例模式。当您需要一个单身来封装JVM生命周期的委托者时,这特别有用。例如,在Scala中编写一个简单的HTTP客户端库,您可以在其中封装基于底层Java实现的委托人,并使API的使用者生活在纯净的世界中。


0

如果在同一个文件中用相同的名称定义类和对象,则它们称为伴随类和对象。Scala没有static as JAVA关键字,您可以在Scala中将其替换为伴随类和对象的static。

有关更多详细信息,请在scala编程中检查文章 类和对象关键字


-1

首先,它提供了静态方法与非静态方法之间的清晰区分。还提供了创建单例类的简单方法。

它还可以继承其他类和/或特征的方法,而Java静态方法无法做到这一点,并且可以将其作为参数传递。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.