Разница между объектом и классом в Scala

636

Я просто просматриваю некоторые учебники по Scala в Интернете и заметил, что в некоторых примерах объект объявляется в начале примера.

В чем разница между classи objectв Scala?

Стив
источник

Ответы:

580

ТЛ; др

  • class C определяет класс, как в Java или C ++.
  • object Oсоздает одноэлементный объект Oкак экземпляр некоторого анонимного класса; его можно использовать для хранения статических членов, которые не связаны с экземплярами какого-либо класса.
  • object O extends Tделает объект Oэкземпляром trait T; затем вы можете пройти Oкуда угодно, Tожидается.
  • если есть class C, то object Cэто сопутствующий объект класса C; обратите внимание, что объект-компаньон не является экземпляром автоматически C.

Также см. Документацию Scala для объекта и класса .

object как множество статических членов

Чаще всего вам нужно objectхранить методы и значения / переменные, которые должны быть доступны без необходимости сначала создавать экземпляр некоторого класса. Это использование тесно связано с staticчленами в Java.

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

Затем вы можете вызвать вышеуказанный метод, используя A.twice(2).

Если бы вы twiceбыли членом какого-то класса A, вам сначала нужно создать экземпляр:

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

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

Вы можете видеть, насколько это избыточно, так как twiceне требует каких-либо специфических для экземпляра данных.

object как особый именованный экземпляр

Вы также можете использовать objectсебя как особый экземпляр класса или черты. Когда вы делаете это, ваш объект должен расширять некоторые trait, чтобы стать экземпляром его подкласса.

Рассмотрим следующий код:

object A extends B with C {
  ...
}

В этом объявлении сначала объявляется анонимный (недоступный) класс, который расширяет как Bи C, так и создает экземпляр одного экземпляра этого класса с именем A.

Это средство Aможет быть передано функциям, ожидающим объекты типа Bили C, или B with C.

Дополнительные функции object

Существуют также некоторые особенности объектов в Scala. Рекомендую прочитать официальную документацию .

  • def apply(...) включает обычный безымянный синтаксис метода A(...)
  • def unapply(...)позволяет создавать собственные экстракторы сопоставления с образцом
  • если сопровождает класс с тем же именем, объект принимает на себя особую роль при разрешении неявных параметров
ziggystar
источник
38
Он также определит класс A и создаст все методы в объекте A как статические методы в классе A (для взаимодействия с Java). (По модулю ошибка в Scala 2.7, которая была исправлена ​​в Scala 2.8)
Кен Блум
2
@KenBloom действительно? Я пробовал и не работает: scala> Commerce res8: Commerce.type = Commerce $ @ 6eb2756 scala> classOf [Commerce] <console>: 23: ошибка: не найдена: введите Commerce classOf [Commerce] ^ scala> new Commerce < консоль>: 23: ошибка: не найдена: введите Commerce new Commerce ^
Hendy Irawan
3
@Hendy: Scala не распознает Commerceкласс, но JVM и язык Java узнают . (Это то, что вы можете сделать object Foo{ def main(args:Seq[String]) }и ожидать запуска программы.)
Кен Блум
3
Я думаю, что ответ ziggystar является более точным, класс является анонимным классом, если только соответствующий класс с именем Commerce не определен явно (тогда объект Commerce будет сопутствующим объектом для класса Commerce)
Hendy Irawan
3
@DavidApltauer Бьюсь об заклад, достаточно тонкостей, которые не покрыты моим ответом. Но это, вероятно, не имеет значения для большинства людей, читающих это. И у меня никогда не было проблем с передачей объекта в качестве примера какой-то черты, что не означает, что они не существуют; но это должно работать.
Ziggystar
249

А classэто определение, описание. Он определяет тип с точки зрения методов и состава других типов.

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

Существует взаимосвязь между objectи class. Объект называется объектом-компаньоном класса, если они имеют одно и то же имя. Когда это происходит, у каждого есть доступ к методам privateвидимости в другом. Эти методы не импортируются автоматически. Вы должны либо импортировать их явно, либо добавить к имени класса / объекта префикс.

Например:

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
   }
}
Даниэль С. Собрал
источник
1
Извините, что беспокою вас, но не могли бы вы указать на пример о том, как импортировать методы в объект-компаньон или как их префикс?
ithkuil
4
@ithkuil Готово. Извините за глупый пример, я не мог придумать хороший и короткий.
Даниэль С. Собрал
Что если я хочу использовать метод класса в Object? Это будет возможно? Если у меня есть метод класса, и я хочу использовать его в Object, то, если вы попытаетесь импортировать класс, вы не сможете. В конце концов вы должны сделать конструктор и затем вызвать метод. Таким образом, создавая объект-компаньон, вы можете получить доступ к методам Object, используя импорт, но не наоборот. Может кто-нибудь, пожалуйста, подтвердите?
ПиюшГоял
@piyushGoyal Не правда. Скажем, у объекта есть метод def f(x: X) = ???, и он сможет вызывать частные методы xкласса-компаньона X.
Даниэль С. Собрал,
Здесь X, переданный в функцию, является экземпляром класса XI догадаться? Если да, то в конечном итоге вы используете объект x для вызова метода класса X в def f .. Верно?
ПиюшГоял
76

Объект имеет ровно один экземпляр (вы не можете вызвать new MyObject). Вы можете иметь несколько экземпляров класса.

Объект служит тем же (и некоторым дополнительным) целям, что и статические методы и поля в Java.

Томас Юнг
источник
19

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

  • Это может быть сопутствующий объект к class/ trait, содержащий то, что можно считать статическими методами или вспомогательными методами.

  • Он может действовать как модуль, содержащий связанные / вспомогательные типы и определения и т. Д.

  • Он может реализовать интерфейс, расширяя classодин или несколько traitсимволов.

  • Он может представлять собой случай, sealed traitкоторый не содержит данных. В этом отношении он часто считается более правильным, чем case classбез параметров. Особый случай использования sealed traitтолько с case objectразработчиками - это более или менее версия перечисления для Scala.

  • Это может служить доказательством implicitлогики.

  • Он вводит одноэлементный тип.

Это очень мощная и общая конструкция. Новичков в Scala может смутить то, что одна и та же конструкция может иметь совершенно разные применения. И они objectмогут одновременно обслуживать многие из этих различных видов использования, что может быть еще более запутанным.

acjay
источник
18

Определение объекта в Scala похоже на определение класса в Java, который имеет только статические методы. Однако в Scala объект может расширять другой суперкласс, реализовывать интерфейсы и передаваться, как если бы он был экземпляром класса. (Так что это как статические методы в классе, но лучше).

Кен Блум
источник
17

Формальная разница -

  1. Вы не можете предоставить параметры конструктора для объектов
  2. Объект не является типом - вы не можете создавать экземпляр с новым оператором. Но он может иметь поля, методы, расширять суперкласс и смешивать черты.

Разница в использовании:

  • Scala не имеет статических методов или полей. Вместо этого вы должны использовать object. Вы можете использовать его с или без связанного класса. В 1-м случае это называется объектом-компаньоном. Вы должны:
    1. используйте одно и то же имя для класса и объекта
    2. поместите их в один и тот же исходный файл.
  • Для создания программы вы должны использовать метод main object, а не in class.

    object Hello {
      def main(args: Array[String]) {
        println("Hello, World!")
      }
    }
  • Вы также можете использовать его как одноэлементный объект в Java.

      
        
      

irudyak
источник
«Вы не можете предоставить параметры конструктора для Объектов» Объекты имеют метод apply (...), который функционирует во многом как конструктор. Это оставляет меня немного смущенным.
Даниэль
7

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

Scala не имеет эквивалента статическому ключевому слову Java , и в Scala часто используется объект, где вы можете использовать класс со статическими членами в Java.


источник
6

Объект является классом, но у него уже есть (есть) экземпляр, поэтому вы не можете вызвать его new ObjectName. С другой стороны, Class это просто тип, и он может быть экземпляром, вызывая new ClassName().

Ёнгу Но
источник
4

В скале нет staticпонятия. Таким образом, scala создает одноэлементный объект, чтобы обеспечить точку входа для выполнения вашей программы. Если вы не создадите одноэлементный объект, ваш код успешно скомпилируется, но не выдаст никакого вывода. Методы, объявленные внутри Singleton Object, доступны глобально. Одноэлементный объект может расширять классы и признаки.

Пример объекта 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")  
    }  
}  

Вывод:

Hello, This is Singleton Object

В scala, когда у вас есть класс с тем же именем, что и у одноэлементного объекта, он называется сопутствующим классом, а одноэлементный объект называется сопутствующим объектом.

Сопутствующий класс и его сопутствующий объект должны быть определены в одном и том же исходном файле.

Пример объекта 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.")  
    }  
}  

Вывод:

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

В Scala класс может содержать:

1. Член данных

2. Метод члена

3. Конструктор Блок

4. Вложенный класс

5. Супер класс информация и т. Д.

Вы должны инициализировать все переменные экземпляра в классе. Там нет области по умолчанию. Если вы не укажете область доступа, она будет общедоступной. Должен быть объект, в котором определен основной метод. Это обеспечивает отправную точку для вашей программы. Здесь мы создали пример класса.

Scala Пример примера класса

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);  
    }  
} 

Извините, я опоздал, но я надеюсь, что это поможет вам.

Бхаскар дас
источник
2

Класс Scala такой же, как класс Java, но Scala не дает вам никакого метода ввода в классе, как метод main в java. Основной метод, связанный с ключевым словом объекта. Вы можете думать о ключевом слове объекта как о создании одноэлементного объекта класса, который определен неявно.

больше информации проверьте этот класс статьи и ключевое слово объекта в программировании Scala

FOD
источник
2

Объект в некоторой степени похож на статический класс в Java, статическая характеристика означает, что статическому классу не нужно создавать объект при помещении в JVM, его можно использовать непосредственно по имени класса и тому же экземпляру (то же состояние данных ) используется там, где он используется.

Дэвид
источник
1

Класс такой же, как и любой другой класс на других языках. Вы определяете класс, как и любой другой язык, с некоторой разницей в синтаксисе.

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

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

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()

Также следует отметить, что класс объектов создается лениво, что является еще одним важным моментом. Таким образом, они не создаются, если они не нужны в нашем коде.

Если вы определяете создание соединения для JDBC, вы можете создать их внутри объекта, чтобы избежать дублирования, как мы делаем в Java с одноэлементными объектами.

Пиюш Патель
источник
0

Если вы исходите из Java, концепция класса в Scala отчасти похожа на Java, но класс в Scala не может содержать статические члены.

Объекты в scala относятся к одноэлементному типу, в котором вы вызываете методы, используя имя объекта, в scala объект - это ключевое слово, а в java - экземпляр класса

Вивек
источник