В чем причина наличия сопутствующих объектов в Scala? - PullRequest
98 голосов
/ 04 марта 2009

Есть ли случай, когда нужен сопутствующий объект (singleton) для класса? Зачем мне создавать класс, скажем Foo, а также создавать для него объект-компаньон?

Ответы [ 7 ]

73 голосов
/ 05 марта 2009

Объект-компаньон в основном предоставляет место, где можно разместить «статические» методы. Кроме того, объект-компаньон или модуль-компаньон имеет полный доступ к членам класса, включая частные.

Сопутствующие объекты отлично подходят для инкапсуляции таких вещей, как фабричные методы. Вместо того, чтобы иметь, например, Foo и FooFactory везде, вы можете иметь класс с сопутствующим объектом, принимающим на себя фабричные обязанности.

60 голосов
/ 20 августа 2010

Сопутствующие объекты полезны для хранения состояния и методов, которые являются общими для всех экземпляров класса , но они не используют статические методы или поля. Они используют обычные виртуальные методы, которые могут быть переопределены через наследование. Скала действительно не имеет ничего статичного. Есть много способов использовать это, но вот простой пример.

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
30 голосов
/ 10 марта 2009

... и это хорошее место для хранения статических фабричных методов (не того DP) для сопровождаемых классов. Если вы называете эти перегруженные фабричные методы apply (/ ... /), вы сможете создать / инициализировать свой класс

  1. без «нового» (не очень важно)

  2. с различными возможными наборами параметров (сравните с тем, что Блох пишет в 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, потому что он не выглядит плохо: как создание чего-то абстрактного. Дайте этим именам реальный смысл. Подумайте об использовании неизменяемых, метода less, классов case и запечатайте абстрактный базовый класс.

19 голосов
/ 05 марта 2009

В дополнение к тому, что Саэм сказал в своем ответе , компилятор Scala также ищет неявных преобразований типов в соответствующих объектах-компаньонах (источника или цели). поэтому конверсии не нужно импортировать.

О причине одиночных объектов в целом Программирование в Scala говорит:

Как упоминалось в главе 1, один из способов, с помощью которого Scala является более объектно-ориентированным, чем Java, состоит в том, что классы в Scala не могут иметь статических членов. Вместо этого в Scala есть одноэлементные объекты (стр. 65).

3 голосов
/ 11 мая 2015

Я всегда вижу сопутствующие объекты как мост для написания как функционального, так и объектно-ориентированного кода в Scala. Много раз нам просто нужны чистые функции, которые принимают некоторый ввод и обеспечивают результат обработки. Помещение этих соответствующих функций в объект-компаньон облегчает поиск и использование, как для меня, так и для одного здания поверх моего кода.

Кроме того, это функция, предоставляемая языком, для написания одноэлементного шаблона без каких-либо действий. Это особенно полезно, когда вам нужен синглтон для инкапсуляции делегатора на всю жизнь JVM. Например, написание простой клиентской библиотеки HTTP в Scala, в которой вы можете инкапсулировать базовый делегатор на основе реализации Java и позволить потребителям вашего API жить в чистом мире.

0 голосов
/ 02 ноября 2017

Во-первых, он обеспечивает четкое разделение статических и нестатических методов. Также предоставляется простой способ создания одноэлементного класса.

Он также может наследовать методы от других классов и / или признаков, что невозможно сделать статическими методами Java. И может быть передано в качестве параметра.

0 голосов
/ 22 июня 2017

Если вы определяете класс и объект в одном файле с одинаковым именем, они называются сопутствующим классом и объектом. В Scala отсутствует статическое ключевое слово JAVA. Вы можете использовать в качестве замены статического класса класс и объект в Scala.

Для более подробной информации, пожалуйста, проверьте статью ключевое слово класса и объекта в scala-программировании

...