Использование Null/Nothing/Unit в Scala
Я только что прочитал: http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/
Насколько я понимаю, Null
является признаком, и его единственным экземпляром является Null
.
Когда метод принимает аргумент Null, мы можем передать его только ссылку Null
или Null
напрямую, но не любую другую ссылку, даже если она равна null (nullString: String = null
например).
Мне просто интересно, в каких случаях использование этой черты Null
может оказаться полезным.
Существует также черта "Ничего", для которой я больше не вижу примеров.
Я действительно не понимаю, какая разница между использованием Nothing и Unit в качестве типа возврата, поскольку оба не возвращают никакого результата, как узнать, какой из них использовать, когда у меня есть метод, который выполняет регистрацию, например
Есть ли у вас использование Unit/Null/Nothing как нечто иное, чем тип возврата?
Ответы
Ответ 1
Вы используете только Nothing, если метод никогда не возвращается (что означает, что он не может нормально завершиться возвратом, он может вызвать исключение). Ничто никогда не создавалось и не существует в пользу системы типов (цитирует Джеймса Ири: "Причина Scala имеет нижний тип, привязанный к его способности для выражения дисперсии параметров типа." ). Из статьи, которую вы связали с:
Другое использование Nothing - это возвращаемый тип для методов, которые никогда не используются вернуть. Это имеет смысл, если вы думаете об этом. Если методы возвращаются type is Nothing, и нет абсолютно никакого примера Nothing, то такой метод никогда не должен возвращаться.
Ваш метод ведения журнала вернет Unit. Существует единица значений, поэтому она может быть фактически возвращена. Из API docs:
Единица - это подтип scala.AnyVal. Существует только одно значение типа Unit,(), и он не представлен никаким объектом в базовом времени выполнения. Метод с возвратом типа Unit аналогичен Java метод, объявленный недействительным.
Ответ 2
Статья, которую вы цитируете, может вводить в заблуждение. Тип Null
существует для совместимости с виртуальной машиной Java и, в частности, с Java.
Мы должны учитывать, что Scala:
- полностью объектно-ориентированное: каждое значение является объектом
- строго типизирован: каждое значение должно иметь тип
- должен обрабатывать ссылки
Null
для доступа, например, библиотеки Java и код
поэтому становится необходимо определить тип для значения Null
, который является признаком Null
, и имеет Null
как единственный экземпляр.
Нет ничего особенно полезного в типе Null
, если вы не являетесь системой типов или не разрабатываете компилятор. В частности, я не вижу разумной причины определять параметр типа Null
для метода, поскольку вы не можете передать ничего, кроме Null
Ответ 3
У вас есть использование Unit/Null/Nothing как нечто иное, чем возвращаемый тип?
Unit
можно использовать следующим образом:
def execute(code: => Unit):Unit = {
// do something before
code
// do something after
}
Это позволяет вам передать произвольный блок кода, который будет выполнен.
Null
может использоваться как нижний тип для любого значения, которое является нулевым. Пример:
implicit def zeroNull[B >: Null] =
new Zero[B] { def apply = null }
Nothing
используется в определении None
object None extends Option[Nothing]
Это позволяет назначить None
любому типу Option
, потому что Nothing
"расширяет" все.
val x:Option[String] = None
Ответ 4
Я никогда не использовал тип Null
, но вы используете Unit
, где вы используете java для использования void
. Nothing
- особый тип, поскольку, как уже упоминал Натан, не может быть экземпляра Nothing
. Nothing
- это так называемый нижний тип, что означает, что он является подтипом любого другого типа. Этот (и параметр контравариантного типа) заключается в том, что вы можете добавить любое значение к Nil
- который является List[Nothing]
- и тогда список будет иметь этот тип элементов. None
также, если тип Option[Nothing]
. Каждая попытка доступа к значениям внутри такого контейнера генерирует исключение, потому что это единственный допустимый способ возврата из метода типа Nothing
.
Ответ 5
если вы используете Nothing
, нет никаких вещей (включая консоль печати)
если вы что-то делаете, используйте тип вывода Unit
object Run extends App {
//def sayHello(): Nothing = println("hello?")
def sayHello(): Unit = println("hello?")
sayHello()
}
... то как использовать Nothing
?
trait Option[E]
case class Some[E](value: E) extends Option[E]
case object None extends Option[Nothing]
Ответ 6
Ничего не используется неявно. В приведенном ниже коде, val b: Boolean =
if (1 > 2) false
else throw new RuntimeException("error")
предложение else имеет тип Ничего, который является подклассом Boolean (как и любой другой AnyVal). Таким образом, все присваивание действительно для компилятора, хотя предложение else ничего не возвращает.
Ответ 7
Вот пример Nothing
from scala.predef
:
def ??? : Nothing = throw new NotImplementedError
Если вы незнакомы (и поисковые системы не могут найти на нем) ???
является функцией Scala placeholder для всего, что еще не реализовано. Также как Котлин TODO
.
Вы можете использовать тот же трюк при создании макетных объектов: переопределить неиспользуемые методы с помощью специального метода notUsed
. Преимущество не использовать ???
заключается в том, что вы не получите компиляции предупреждений о вещах, которые вы никогда не намерены реализовать.
Ответ 8
В терминах теории категорий Ничто не является начальным объектом, а Unit является терминальным объектом.
https://en.wikipedia.org/wiki/Initial_and_terminal_objects