В чем причина наличия сопутствующих объектов в Scala?

StackOverflow https://stackoverflow.com/questions/609744

  •  03-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

Другие советы

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

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

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

<Ол>
  • без «нового» (не очень важно)

  • с различными возможными наборами параметров (сравните с тем, что Блох пишет в Effective Java о конструкторе телескопирования)

  • с возможностью решать, какой производный класс вы хотите создать вместо абстрактного (сопровождающего) класса

  • Пример кода:

    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 и закройте абстрактный базовый класс.

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

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

      

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

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

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

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

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

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

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top