Как примитивы типов объектов в Scala? - PullRequest
1 голос
/ 16 июня 2020

Как выглядят примитивные типы в Scala объектах, если мы не используем слово «новый» для создания экземпляров этих примитивов? Программирование в Scala Мартином Одерски описало рассуждения как некоторую принудительную с помощью «уловки», которая делает эти классы значений абстрактными и окончательными, что не совсем имело для меня смысла, потому что как мы можем создать экземпляры этих классов классы, если его абстрактные? Если тот же самый примитивный литерал должен где-то храниться, скажем, в переменной, сделает ли переменная объектом?

1 Ответ

1 голос
/ 16 июня 2020

Я предполагаю, что вы используете scala 2.13 с реализацией литеральных типов . Для этого объяснения вы можете рассматривать type и class как синонимы, но на самом деле это разные концепции.

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

Итак, литерал 1 является значением и типом одновременно (экземпляр 1 типа 1), и это подтип класса значений Int.

Давайте докажем, что 1 является подтипом Int, используя 'неявно':

implicitly[1 <:< Int] // compiles

То же, но используя val:

val one:1 = 1
implicitly[one.type <:< Int] // compiles

Итак one - это вид экземпляр (объект) типа 1 (и одновременно экземпляр типа Int, потому что Int является супертипом 1). Вы можете использовать это значение так же, как и любые другие объекты (передать его функции или присвоить другому vals et c).

val one:1 = 1
val oneMore: 1 = one
val oneMoreGeneric: Int = one
val oneNew:1 = 1

Мы можем предположить, что все эти vals содержат один и тот же экземпляр одного объекта, потому что с практической точки зрения не имеет значения, является это тем же объектом или нет.

Технически это вообще не объект, потому что примитивы возникли из мира java (JVM), где примитивы не являются объектами. Это разные сущности.

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

Но вот некоторые различия за кулисами. Каждый класс значений является подтипом AnyVal, но остальные классы являются подтипом AnyRef (обычный класс).

implicitly[1 <:< AnyVal] //compiles 
implicitly[Int <:< AnyVal] // compiles

trait AnyTraint
implicitly[AnyTraint <:< AnyVal] // fails to compail
implicitly[AnyTraint <:< AnyRef] // compiles

И, кроме того, из-за его неклассовой природы в JVM, вы не можете расширить value classes как обычный класс или использовать new для создания экземпляра (потому что scala компилятор эмулирует new сам по себе). Вот почему с точки зрения расширения классов значений вы должны думать о них как о final и с точки зрения создания экземпляров вручную вы должны думать о них как о абстрактных . Но в большинстве других точек зрения он похож на любой другой обычный класс.

Итак, scala компилятор может своего рода расширять Int на 1,2,3 .. типы и создавать их экземпляры для vals, но разработчики не могут сделать это вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...