Was ist der Grund für das Vorhandensein von Begleitobjekten in Scala?

Antworten:

82

Das Begleitobjekt bietet im Grunde einen Ort, an dem man "statische" Methoden einsetzen kann. Darüber hinaus hat ein Begleitobjekt oder Begleitmodul vollen Zugriff auf die Klassenmitglieder, einschließlich privater.

Begleitobjekte eignen sich hervorragend zum Einkapseln von Dingen wie Factory-Methoden. Anstatt zum Beispiel Foound FooFactoryüberall zu haben, können Sie eine Klasse mit einem Begleitobjekt die Fabrikverantwortung übernehmen lassen.

Saem
quelle
61

Companion-Objekte sind nützlich zum Speichern von Status und Methoden, die allen Instanzen einer Klasse gemeinsam sind , jedoch keine statischen Methoden oder Felder verwenden. Sie verwenden reguläre virtuelle Methoden, die durch Vererbung überschrieben werden können. Scala hat wirklich nichts Statisches. Es gibt viele Möglichkeiten, wie Sie dies verwenden können, aber hier ist ein einfaches Beispiel.

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
}

Welches erzeugt diese Ausgabe:

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
Craig P. Motlin
quelle
1
Eine ähnliche Abbildung finden Sie auch hier: daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik
30

... und es ist ein guter Ort, um statische Factory-Methoden (nicht diesen DP) für begleitete Klassen zu speichern. Wenn Sie diese überladenen Factory-Methoden angeben (/ ... /), können Sie Ihre Klasse erstellen / initialisieren

  1. ohne 'neu' (nicht wirklich so wichtig)

  2. mit verschiedenen möglichen Parametersätzen (vergleiche mit dem, was Bloch in Effective Java über den Teleskopkonstruktor schreibt)

  3. mit der Möglichkeit zu entscheiden, welche abgeleitete Klasse Sie anstelle der abstrakten (begleiteten) Klasse erstellen möchten

Beispielcode:

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

Ich würde die Objekt- / Basisklasse AbstractXxxxx nicht nennen, weil sie nicht schlecht aussieht: als würde man etwas Abstraktes erstellen. Geben Sie diesen Namen eine echte Bedeutung. Erwägen Sie die Verwendung unveränderlicher Fallmethoden ohne Methode und versiegeln Sie die abstrakte Basisklasse.

Szymon Jachim
quelle
2
RealThingund AlternativeThingclass sollte einen privateKonstruktor haben, der den Benutzer zwingt, die AbstractClasshas-Factory zu verwenden. class AlternativeThing private(i: Int) extends AbstractClass
Metch
@ [Szymon Jachim] Die abstrakte Scala-Klasse unterstützt keine Mehrfachvererbung. Warum lässt der Compiler dies in Ihrem Fall zu?
user2441441
19

Zusätzlich zu den Dingen Saem sagte in seiner Antwort sucht der Scala - Compiler auch für implizite Konvertierungen von Typen in den entsprechenden Begleiter Objekte (von der Quelle oder Ziel), so dass die Umwandlungen nicht importiert werden müssen.

Über den Grund für Singleton-Objekte in der allgemeinen Programmierung in Scala heißt es:

Wie in Kapitel 1 erwähnt, besteht eine Möglichkeit, in der Scala objektorientierter als Java ist, darin, dass Klassen in Scala keine statischen Elemente haben können. Stattdessen verfügt Scala über Singleton-Objekte (S. 65).

Fabian Steeg
quelle
3

Ich sehe Begleitobjekte immer als Brücke , um sowohl funktionalen als auch objektorientierten Code in Scala zu schreiben. Oft brauchen wir nur reine Funktionen, die Eingaben benötigen und ein Verarbeitungsergebnis liefern. Das Einfügen dieser relevanten Funktionen in das Begleitobjekt erleichtert das Nachschlagen und Verwenden sowohl für mich selbst als auch für jemanden, der auf meinem Code aufbaut.

Darüber hinaus ist es eine sprachlich bereitgestellte Funktion, um das Singleton-Muster zu schreiben, ohne etwas zu tun. Dies ist besonders nützlich, wenn Sie einen Singleton benötigen, um einen Delegator für die Lebensdauer von JVM zu kapseln. Schreiben Sie beispielsweise eine einfache HTTP-Clientbibliothek in Scala, in der Sie einen zugrunde liegenden Java-Implementierungsdelegator kapseln und die Benutzer Ihrer API in einer reinen Welt leben lassen können.

Gaurav Abbi
quelle
0

Wenn Sie Klasse und Objekt in derselben Datei mit demselben Namen definieren, werden sie als Begleitklasse und Objekt bezeichnet. Scala hat kein statisches JAVA-Schlüsselwort. Sie können statisches als Begleitklasse und Objekt in Scala ersetzen.

Weitere Informationen finden Sie in der Scala-Programmierung unter Artikelklasse und Objektschlüsselwort

FOD
quelle
-1

Zunächst bietet es eine klare Trennung zwischen statischen und nicht statischen Methoden. Außerdem bietet es eine einfache Möglichkeit, eine Singleton-Klasse zu erstellen.

Es kann auch Methoden von anderen Klassen und / oder Merkmalen erben, was mit statischen Java-Methoden nicht möglich ist. Und kann als Parameter übergeben werden.

Vipin
quelle