Що обґрунтовує наявність об'єктів-супутників у Скалі?


107

Чи є випадок, коли потрібний супутниковий об’єкт (синглтон) для класу? Чому я б хотів створити клас, скажімо, Fooа також створити для нього об’єкт-супутник?



Дивіться також stackoverflow.com/a/9806136/736957, який є хорошим складанням відповідей тут
laughhedelic

Відповіді:


82

Об’єкт-супутник в основному забезпечує місце, де можна поставити "статичні" методи. Крім того, супутній об’єкт або супутниковий модуль має повний доступ до членів класу, включаючи приватні.

Об'єкти-супутники чудово підходять для інкапсуляції таких речей, як заводські методи. Замість того, щоб мати, наприклад, Fooі FooFactoryскрізь, ви можете мати клас із супутнім об'єктом, який бере на себе заводські обов'язки.


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

30

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

  1. без "нового" (не дуже важливо)

  2. з різними можливими наборами параметрів (порівняйте те, що Bloch пише в Ефективній 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
RealThingі AlternativeThingклас повинен мати privateконструктор, щоб змусити користувача користуватися AbstractClassзаводом has. class AlternativeThing private(i: Int) extends AbstractClass
metch

@ [Szymon Jachim] Абстрактний клас Scala не підтримує множинне успадкування. То чому компілятор допускає це у вашому випадку?
користувач2441441

19

Окрім речей, які сказав Сам у своїй відповіді , компілятор Scala також шукає неявні перетворення типів у відповідних супутніх об'єктах (або джерела, або цілі), тому перетворення не потрібно імпортувати.

Про причину одиночних об'єктів взагалі програмування в Scala говорить:

Як було сказано в главі 1, одним із способів, в якому Scala є більш орієнтованим на об'єкти, ніж Java, є те, що класи в Scala не можуть мати статичних членів. Натомість у Scala є одиночні об'єкти (стор. 65).


3

Я завжди бачу супутні об'єкти як міст, щоб написати як функціональний, так і об'єктно-орієнтований код у Scala. Багато разів нам просто потрібні чисті функції, які беруть певний вклад і забезпечують результат обробки. Якщо помістити ці відповідні функції в супровідний об'єкт, це полегшує пошук і використання як для себе, так і для деякої однієї будівлі поверх мого коду.

Більше того, це мовна функція, щоб написати однотонний візерунок, не роблячи нічого. Це особливо корисно, коли вам потрібен сингл для інкапсуляції делегатора протягом життя JVM. Наприклад, написання простої бібліотеки клієнтів HTTP у Scala, де ви можете інкапсулювати базовий делегатор на базі впровадження Java та дозволити споживачам вашого API жити в чистому світі.


0

Якщо ви визначаєте клас і об’єкт у тому ж файлі з однаковою назвою, вони відомі як супутні клас та об’єкт. Scala не мають статики як ключове слово JAVA. Ви можете взяти заміну статики класом-супутником та об'єктом у Scala.

Для отримання більш детальної інформації, будь ласка, ознайомтеся з класом статті та об'єктом ключового слова в програмі Scala


-1

Спочатку він забезпечує чіткий поділ методів статичних проти нестатичних методів. Також пропонується простий спосіб створення одиночного класу.

Він також може успадковувати методи з інших класів та / або ознак, що неможливо зробити із статичними методами Java. І може передаватися як параметр.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.