Różnica między przedmiotem a klasą w Scali

635

Właśnie przeglądam kilka samouczków Scali w Internecie i zauważyłem w niektórych przykładach, że obiekt został zadeklarowany na początku przykładu.

Jaka jest różnica między classi objectw Scala?

Steve
źródło

Odpowiedzi:

578

tl; dr

  • class C definiuje klasę, tak jak w Javie lub C ++.
  • object Otworzy obiekt singletonuO jako instancję jakiejś anonimowej klasy; może być używany do przechowywania elementów statycznych, które nie są powiązane z instancjami niektórych klas.
  • object O extends Tczyni obiekt Oprzykładem trait T; następnie możesz przejść Ogdziekolwiek, Toczekuje się.
  • jeśli istnieje class C, to object Cjest to obiekt towarzyszący klasy C; zwróć uwagę, że obiekt towarzyszący nie jest automatycznie instancją C.

Zobacz także dokumentację Scali dla obiektu i klasy .

object jako host członków statycznych

Najczęściej potrzebujesz objectmetody i wartości / zmiennych, które powinny być dostępne bez konieczności tworzenia instancji jakiejś klasy. To użycie jest ściśle związane z staticczłonkami w Javie.

object A {
  def twice(i: Int): Int = 2*i
}

Następnie możesz wywołać powyższą metodę za pomocą A.twice(2).

Gdyby twicebył członkiem jakiejś klasy A, najpierw musiałbyś utworzyć instancję:

class A() {
  def twice(i: Int): Int = 2 * i
}

val a = new A()
a.twice(2)

Możesz zobaczyć, jak to jest zbędne, ponieważ twicenie wymaga żadnych danych specyficznych dla instancji.

object jako specjalne nazwane wystąpienie

Możesz także użyć objectsiebie jako specjalnego wystąpienia klasy lub cechy. Kiedy to zrobisz, twój obiekt musi rozszerzyć część trait, aby stać się instancją jego podklasy.

Rozważ następujący kod:

object A extends B with C {
  ...
}

Ta deklaracja pierwszy deklaruje anonimowy (niedostępne), który rozciąga się zarówno klasę Bi Coraz instancję jedno wystąpienie tej klasy o nazwie A.

Oznacza to, że Amożna przekazać funkcje oczekujące obiektów typu Blub C, lub B with C.

Dodatkowe funkcje object

Istnieją również specjalne cechy obiektów w Scali. Polecam przeczytać oficjalną dokumentację .

  • def apply(...) włącza zwykłą składnię bez nazwy metody A(...)
  • def unapply(...)pozwala na tworzenie niestandardowych ekstraktorów dopasowujących wzór
  • jeśli towarzyszy klasie o tej samej nazwie, obiekt przyjmuje szczególną rolę podczas rozwiązywania niejawnych parametrów
ziggystar
źródło
38
Zdefiniuje również klasę A i utworzy wszystkie metody w obiekcie A jako metody statyczne w klasie A (do połączenia z Javą). (Modulo błąd w Scali 2.7, który został naprawiony w Scala 2.8)
Ken Bloom
2
@KenBloom naprawdę? Próbowałem i nie działa: scala> Commerce res8: Commerce.type = Commerce $ @ 6eb2756 scala> classOf [Commerce] <console>: 23: error: not found: type Commerce classOf [Commerce] ^ scala> new Commerce < konsola>: 23: błąd: nie znaleziono: wpisz Commerce nowy Commerce ^
Hendy Irawan
3
@Hendy: Scala nie rozpozna Commerceklasy, ale JVM i język Java to zrobią. (Tak możesz zrobić object Foo{ def main(args:Seq[String]) }i oczekiwać, że program się uruchomi.)
Ken Bloom,
3
Myślę, że odpowiedź ziggystar jest bardziej precyzyjna, klasa jest klasą anonimową, chyba że odpowiednia klasa o nazwie Commerce jest wyraźnie zdefiniowana (wtedy obiekt Commerce będzie obiektem towarzyszącym klasie Commerce)
Hendy Irawan,
3
@DavidApltauer Założę się, że jest wystarczająco dużo subtelności, które nie są objęte moją odpowiedzią. Ale te prawdopodobnie nie mają znaczenia dla większości ludzi, którzy to czytają. I nigdy nie miałem problemów z przekazywaniem obiektu jako instancji jakiejś cechy, co nie znaczy, że nie istnieją; ale powinno działać.
ziggystar
249

A classjest definicją, opisem. Definiuje typ pod względem metod i składu innych typów.

An objectjest singletonem - wystąpieniem klasy, która gwarantuje wyjątkowość. Dla każdego objectw kodzie tworzona jest anonimowa klasa, która dziedziczy po wszystkich klasach, które zadeklarowałeś objectdo zaimplementowania. Tej klasy nie można zobaczyć z kodu źródłowego Scali - choć można do niej dojść poprzez refleksję.

Istnieje związek między objecti class. Mówi się, że obiekt jest obiektem towarzyszącym klasy, jeśli mają tę samą nazwę. Kiedy tak się dzieje, każdy ma dostęp do metod privatewidoczności w drugim. Te metody nie są jednak automatycznie importowane. Musisz je zaimportować jawnie lub poprzedzić je nazwą klasy / obiektu.

Na przykład:

class X {
  // class X can see private members of object X
  // Prefix to call
  def m(x: Int) = X.f(x)

  // Import and use
  import X._
  def n(x: Int) = f(x)

  private def o = 2
}

object X {
  private def f(x: Int) = x * x

  // object X can see private members of class X
  def g(x: X) = {
    import x._
    x.o * o // fully specified and imported
   }
}
Daniel C. Sobral
źródło
1
Przepraszam, że przeszkadzam, ale czy mógłbyś wskazać przykład na temat importowania metod do obiektu towarzyszącego lub ich prefiksu?
ithkuil
4
@ithkuil Gotowe. Przepraszam za głupi przykład, nie mogłem wymyślić dobrego i krótkiego.
Daniel C. Sobral,
Co jeśli chcę użyć metod klasy w Object? Czy będzie to możliwe? Jeśli mam metodę klasy i chcę jej użyć w Object, to jeśli spróbujesz zaimportować klasę, nie będziesz w stanie tego zrobić. W końcu musisz stworzyć konstruktor i wywołać metodę. Tak więc, tworząc obiekt towarzyszący, możesz uzyskać dostęp do metod Object przy użyciu importu, ale nie odwrotnie. Czy ktoś może potwierdzić?
piyushGoyal
@piyushGoyal Nieprawda. Powiedzmy, że obiekt ma metodę def f(x: X) = ???, a następnie będzie mógł wywoływać metody prywatne xklasy towarzyszącej X.
Daniel C. Sobral
Tutaj X przekazany w funkcji jest instancją klasy XI, zgadujesz? Jeśli tak, to w końcu używasz obiektu x do wywołania metody klasy X w definicji f .. Prawda?
piyushGoyal
76

Obiekt ma dokładnie jedną instancję (nie można wywołać new MyObject). Możesz mieć wiele instancji klasy.

Obiekt służy tym samym (i niektórym dodatkowym) celom, jak metody statyczne i pola w Javie.

Thomas Jung
źródło
19

Jak zostało wyjaśnione przez wielu, objectdefiniuje instancję singletonu. Jedyną rzeczą w odpowiedziach tutaj, którą moim zdaniem pominięto, jest to, że objectsłuży ona kilku celom.

  • Może to być obiekt towarzyszący do class/ trait, zawierający coś, co można uznać za metody statyczne lub metody wygody.

  • Może działać podobnie jak moduł, zawierający pokrewne / pomocnicze typy i definicje itp.

  • Może implementować interfejs poprzez rozszerzenie classjednego lub więcej traits.

  • Może reprezentować przypadek, sealed traitktóry nie zawiera danych. Pod tym względem często uważa się to za bardziej poprawne niż case classbez parametrów. Szczególnym przypadkiem sealed traitz tylko case objectimplementatorami jest mniej więcej wersja wyliczenia Scala.

  • Może działać jako dowód na implicitlogikę napędzaną.

  • Wprowadza typ singletonu.

To bardzo mocna i ogólna konstrukcja. To, co może być bardzo mylące dla początkujących Scali, to fakt, że ten sam konstrukt może mieć bardzo różne zastosowania. I objectmoże służyć jednocześnie wielu z tych różnych zastosowań, co może być jeszcze bardziej mylące.

acjay
źródło
18

Definiowanie obiektu w Scali jest jak definiowanie klasy w Javie, która ma tylko metody statyczne. Jednak w Scali obiekt może rozszerzać kolejną nadklasę, implementować interfejsy i być przekazywany tak, jakby był instancją klasy. (Więc to jest jak metody statyczne w klasie, ale lepiej).

Ken Bloom
źródło
17

Różnica formalna -

  1. nie można podać parametrów konstruktora dla obiektów
  2. Obiekt nie jest typem - nie możesz utworzyć instancji z nowym operatorem. Ale może mieć pola, metody, rozszerzać nadklasę i mieszać cechy.

Różnica w użyciu:

  • Scala nie ma metod statycznych ani pól. Zamiast tego powinieneś użyćobject . Możesz go używać z pokrewną klasą lub bez niej. W pierwszym przypadku nazywa się to obiektem towarzyszącym. Musisz:
    1. użyj tej samej nazwy zarówno dla klasy, jak i obiektu
    2. umieść je w tym samym pliku źródłowym.
  • Aby utworzyć program, powinieneś użyć metody głównej w object, a nie w class.

    object Hello {
      def main(args: Array[String]) {
        println("Hello, World!")
      }
    }
  • Możesz także użyć go, gdy używasz obiektu singleton w Javie.

      
        
      

irudyak
źródło
„nie można podać parametrów konstruktora dla obiektów” Obiekty mają metodę zastosuj (...), która działa podobnie jak konstruktor. To mnie trochę zdezorientowane.
Danielle,
7

Obiekt kluczowe tworzy nowy typ Singleton, który jest jak klasy , który ma tylko jedno wystąpienie nazwane. Jeśli znasz Javę, zadeklarowanie obiektu w Scali przypomina tworzenie nowej instancji anonimowej klasy.

Scala nie ma odpowiednika statycznego słowa kluczowego Java , a obiekt jest często używany w Scali, gdzie można użyć klasy z elementami statycznymi w Javie.


źródło
6

Obiekt jest klasą, ale ma już (jest) instancję, więc nie można wywoływać new ObjectName. Z drugiej strony, klasa jest po prostu typem i może być instancją przez wywołanie new ClassName().

Yonggoo Noh
źródło
4

W scali nie ma staticpojęcia. Tak więc scala tworzy obiekt singleton, który zapewnia punkt wejścia do wykonania programu. Jeśli nie utworzysz obiektu singleton, kod zostanie pomyślnie skompilowany, ale nie wygeneruje żadnych danych wyjściowych. Metody zadeklarowane w obiekcie Singleton są dostępne globalnie. Obiekt singleton może rozszerzać klasy i cechy.

Przykład obiektu Scala Singleton

object Singleton{  
    def main(args:Array[String]){  
        SingletonObject.hello()         // No need to create object.  
    }  
}  


object SingletonObject{  
    def hello(){  
        println("Hello, This is Singleton Object")  
    }  
}  

Wynik:

Hello, This is Singleton Object

W scali, gdy masz klasę o tej samej nazwie co obiekt singletonu, nazywa się to klasą towarzyszącą, a obiekt singletonu nazywa się obiektem towarzyszącym.

Klasa towarzysząca i jej obiekt towarzyszący muszą być zdefiniowane w tym samym pliku źródłowym.

Przykład obiektu Scala Companion

class ComapanionClass{  
    def hello(){  
        println("Hello, this is Companion Class.")  
    }  
}  
object CompanoinObject{  
    def main(args:Array[String]){  
        new ComapanionClass().hello()  
        println("And this is Companion Object.")  
    }  
}  

Wynik:

Hello, this is Companion Class.
And this is Companion Object.

W scali klasa może zawierać:

1. Członek danych

2. Metoda członka

3. Blok konstruktora

4. Klasa zagnieżdżona

5. Informacje o superklasie itp.

Musisz zainicjować wszystkie zmienne instancji w klasie. Nie ma domyślnego zakresu. Jeśli nie określisz zakresu dostępu, jest on publiczny. Musi istnieć obiekt, w którym zdefiniowana jest metoda główna. Stanowi punkt wyjścia dla twojego programu. Tutaj stworzyliśmy przykład klasy.

Przykład Scali Przykład klasy

class Student{  
    var id:Int = 0;                         // All fields must be initialized  
    var name:String = null;  
}  
object MainObject{  
    def main(args:Array[String]){  
        var s = new Student()               // Creating an object  
        println(s.id+" "+s.name);  
    }  
} 

Przepraszam, spóźniłem się, ale mam nadzieję, że ci to pomoże.

Bhaskar Das
źródło
2

Klasa Scala taka sama jak klasa Java, ale scala nie daje żadnej metody wprowadzania w klasie, takiej jak metoda główna w java. Główna metoda związana ze słowem kluczowym object. Możesz myśleć o słowie kluczowym object jako o utworzeniu obiektu singleton klasy, która jest zdefiniowana niejawnie.

więcej informacji sprawdź tę klasę i słowo kluczowe obiektu w programowaniu scala

FOD
źródło
2

Obiekt jest w pewnym stopniu podobny do klasy statycznej w Javie, charakterystyka statyczna oznacza, że ​​klasa statyczna nie musi tworzyć obiektu podczas wstawiania do JVM, może być używana przez nazwę swojej klasy bezpośrednio i to samo wystąpienie (ten sam stan danych ) jest udostępniany wszędzie tam, gdzie jest używany.

David
źródło
1

Klasa jest jak każda inna klasa w innych językach. Definiujesz klasę jak każdy inny język z pewną różnicą składni.

class Person(val name: String)
val me = new Person("My name")

Jednak obiekt jest klasą zawierającą tylko jeden obiekt. To sprawia, że ​​jest interesujący, ponieważ można go używać do tworzenia statycznych elementów klasy za pomocą obiektu towarzyszącego . Ten obiekt towarzyszący ma dostęp do prywatnych członków definicji klasy i ma taką samą nazwę jak klasa, którą definiujesz.

class Person(var name: String) {

  import Person._

  def hi(): String = sayHello(name)
}

object Person {
  private def sayHello(name: String): String = "Hello " + name
}

val me = new Person("My name")
me.hi()

Warto również zauważyć, że leniwie tworzona jest klasa obiektów, co jest kolejnym ważnym punktem. Nie są one zatem tworzone, chyba że są potrzebne w naszym kodzie.

Jeśli definiujesz tworzenie połączeń dla JDBC, możesz utworzyć je wewnątrz obiektu, aby uniknąć duplikacji, tak jak robimy to w Javie z obiektami singletonowymi.

Piyush Patel
źródło
0

Jeśli pochodzisz z java, pojęcie klasy w scali jest trochę podobne do Javy, ale klasa w scala nie może zawierać elementów statycznych.

Obiekty w scala są typu singleton, który wywołujesz metody wewnątrz niej za pomocą nazwy obiektu, w scala obiekt jest słowem kluczowym, a w obiekcie Java jest instancją klasy

Vivek
źródło