8.2. Klasy i obiekty towarzyszące

Nazwy klas są umieszczane w przestrzeni nazw dotyczącej typów, a nazwy obiektów w przestrzeni nazw dotyczących wartości. Możliwe jest istnienie klasy i obiektu o takich samych nazwach. Obiekt o nazwie takiej, jak klasa, nadaje się do umieszczania w nim metod, których działanie odnosi się w jakiś sposób do instancji klasy, ale nie może być umieszczone w samej klasie. W pliku Objects4.scala znajdują się definicje klasy i obiektu Hello3. Obiekt Hello3 definiuje metodę apply, za pomocą której można tworzyć instancje klasy Hello3.

Plik Objects4.scala:
object Hello3 {
  def apply(greeting: String) = new Hello3(greeting)
}
class Hello3(greeting: String) {
  def speak = println(greeting)
}

Instancje klasy Hello3 mogą być tworzone zarówno poprzez bezpośrednie wywołanie instrukcji new, jak i pośrednio, poprzez wywołanie metody apply (zarówno jawne jak i niejawne).

scala> val a = new Hello3("hello")
a: Hello3 = Hello3@6374ef

scala> val b = Hello3.apply("hi")
b: Hello3 = Hello3@51f34b

scala> val c = Hello3("hi")
c: Hello3 = Hello3@7eb8cb

scala> a.speak
hello

scala> b.speak
hi

scala> c.speak
hi

Jeśli klasa i obiekt o tych samych nazwach są zdefiniowane w tym samym pliku źródłowym, to w takim przypadku klasę nazywamy klasą towarzyszącą obiektu, a obiekt nazywamy obiektem towarzyszącym klasy. Obiekty towarzyszące mają dostęp do prywatnych składowych klas towarzyszących i odwrotnie.

Składowe prywatne są oznaczane modyfikatorem private. Informacje na temat ograniczeń dostępu do składowych klas i obiektów, w tym informacje na temat składowych prywatnych, znajdują się w rozdziale 16.

W pliku Companion1.scala znajdują się definicje obiektu i klasy, które mają takie same nazwy. Obiekt Companion1 jest obiektem towarzyszącym klasy Companion1, a ta klasa jest klasą towarzyszącą tego obiektu.

Plik Companion1.scala:
class Companion1(greeting: String) {
  private def greet1: String = greeting + " (private)"
  def greet2 = Companion1.greet3
}
object Companion1 {
  def apply(greeting: String) = new Companion1(greeting)
  private def greet3: String  = "Hello (private)"
  def greet4(instance: Companion1) = instance.greet1
}

Dostęp do prywatnych metod greet1 oraz greet3 z zewnątrz klasy i obiektu jest zabroniony.

scala> val c1 = Companion1("Hi")
c1: Companion1 = Companion1@12ceb35
scala> c1.greet1
<console>:12: error: method greet1 in class Companion1 cannot be accessed in Companion1
       c1.greet1
          ^

scala> Companion1.greet3
<console>:11: error: method greet3 in object Companion1 cannot be accessed in object Companion1
       Companion1.greet3
                  ^

Natomiast dostęp do tych metod z obiektu i klasy towarzyszącej — z metod greet2 i greet4 — jest możliwy.

scala> c1.greet2
res5: String = Hello (private)

scala> Companion1.greet4(c1)
res6: String = Hi (private)

Pliki Companion2a.scala i Companion2b.scala zawierają podobne definicje obiektu i klasy o takich samych nazwach (Companion2), ale tym razem zdefiniowane w osobnych plikach źródłowych. W konsekwencji, obiekt Companion2 nie jest obiektem towarzyszącym klasy Companion2, a klasa Companion2 nie jest klasą towarzyszącą tego obiektu.

Plik Companion2a.scala:
class Companion2(greeting: String) {
  private def greet1 = println(greeting + " (class private)")
  def greet2 = Companion2.greet3
}
Plik Companion2b.scala:
object Companion2 {
  private def greet3  = println("Hello (object private)")
  def greet4(instance: Companion2) = instance.greet1
}

Obu plików nie udaje się nawet skompilować — ani osobno, ani razem.

$ scalac Companion2a.scala
Companion2a.scala:3: error: not found: value Companion2
  def greet2 = Companion2.greet3
               ^
one error found

$ scalac Companion2b.scala
Companion2b.scala:3: error: not found: type Companion2
  def greet4(instance: Companion2) = instance.greet1
                       ^
one error found

$ scalac Companion2a.scala Companion2b.scala
Companion2b.scala:1: error: Companions 'class Companion2' and 'object Companion2' must be defined in same file:
  Found in H:\jps2\examples\Companion2a.scala and H:\jps2\examples\Companion2b.scala
object Companion2 {
       ^
one error found

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.