Использование 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. Преимущество не использовать ??? заключается в том, что вы не получите компиляции предупреждений о вещах, которые вы никогда не намерены реализовать.