Почему у Scala есть классы, когда у него уже есть черты? - PullRequest
16 голосов
/ 04 декабря 2011

Это может показаться глупым вопросом, так что терпите меня ...

Рассмотрите этот сеанс REPL:

scala> trait T
defined trait T

scala> val t = new T
<console>:8: error: trait T is abstract; cannot be instantiated
       val t = new T
               ^

scala> val t = new T {}
t: java.lang.Object with T = $anon$1@78db81f3

scala> class C
defined class C

scala> val c = new C
c: C = C@170a6001

Мы можем использовать черту, как класс, за исключением того, чтомы должны добавить {} после new T.На самом деле, мы, по сути, смешиваем T в java.lang.Object, что на самом деле имеет для меня большой смысл.

Если у нас есть члены, снова нужно добавить только {}:

scala> trait T2 { val s = "test" }
defined trait T2

scala> val t2 = new T2
<console>:8: error: trait T2 is abstract; cannot be instantiated
       val t2 = new T2
                ^

scala> val t2 = new T2 {}
t2: java.lang.Object with T2 = $anon$1@6a688d6f

scala> t2.s
res0: java.lang.String = test

scala> class C2 { val s = "test" }
defined class C2

scala> val c2 = new C2
c2: C2 = C2@73ea7821

scala> c2.s
res1: java.lang.String = test

Если у нас есть абстрактные члены, то объявление черты на самом деле короче на несколько символов и, что более важно, более согласованно в моих глазах (не нужно помнить, чтобы поставить abstract перед вашими объявлениями):

scala> trait T3 { val s: String }
defined trait T3

scala> val t3 = new T3 { val s = "test" }
t3: java.lang.Object with T3 = $anon$1@1f2f0ce9

scala> abstract class C3 { val s: String }
defined class C3

scala> val c3 = new C3 { val s = "test" }
c3: C3 = $anon$1@207a8313

Если вы забудете, что должны определить некоторые элементы, оба способа дают вам ошибки компиляции:

scala> val badt3 = new T3 {}
<console>:7: error: object creation impossible, since value s in trait T3 of type String is not defined
       val badt3 = new T3 {}

scala> class BadC3 { val s: String }
<console>:8: error: class BadC3 needs to be abstract, since value s is not defined
       class BadC3 { val s: String }

И если мы попытаемся сделать более сложные вещи, тогда сила чертестественно становится еще более очевидным:

scala> val t4 = new T with T2
t4: java.lang.Object with T with T2 = $anon$1@479e0994

scala> val c4 = new C with C2
<console>:9: error: class C2 needs to be a trait to be mixed in
       val c4 = new C with C2

Итак, еще раз я спрашиваю, почему Scala вообще беспокоится об уроках, когда черты, по-видимому, и проще, и мощнее?фактическая совместимость с Java, но мне интересно, можно ли было поддерживать совместимость кода за кулисами.Насколько я понимаю, черты Scala просто становятся закулисными классами Java, так почему же не может произойти обратного, и Scala считает классы Java по существу чертами?скобки когда не нужны?Например:

val t = new T

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

1 Ответ

30 голосов
/ 04 декабря 2011

Существует несколько различий между чертами и классами:

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

  • черта компилируется в интерфейс Java и класс реализации (несущий конкретныйметоды).Это означает, что это немного медленнее, потому что все вызовы проходят через интерфейсы, и если они конкретны, они перенаправляются в свою реализацию

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

Я не думаю, что различие между классами и признакамиуйдет, в основном из-за последних двух предметов.Но они могут стать проще в использовании, если первый пункт решен.Что касается инстанцирования без {}, то это удобство, которое можно добавить, но мне лично это не понравилось бы: каждая инстанциация создает новый класс (анонимный), и должно быть указание напрограммист, что это так.

...