ScalaでのNull / Nothing / Unitの使用法


95

今読んだところ:http : //oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

私が理解している限り、Nullは特性であり、その唯一のインスタンスはnullです。

メソッドがNull引数を取る場合、それをNull参照またはnull直接渡すことができるだけで、それがnullであっても、他の参照は渡せませんnullString: String = null

このNullトレイトを使用することがどのような場合に役立つか疑問に思います。私が実際にこれ以上の例を見ないNothingトレイトもあります。


どちらも結果を返さないので、NothingとUnitを戻り値の型として使用することの違いは本当にわかりません。たとえば、ログを実行するメソッドがある場合、どちらを使用するかを知る方法はありますか?


Unit / Null / Nothingを戻り値の型以外に使用していますか?

回答:


80

メソッドが戻らない場合にのみNothingを使用します(つまり、復帰しても正常に完了できないため、例外がスローされる可能性があります)。何もインスタンス化されることはなく、型システムのメリットのために存在します(James Iryを引用すると、「Scalaに底の型がある理由は、型パラメーターの分散を表現する能力に関係しています。」)。リンクした記事から:

Nothingのもう1つの用途は、決して戻らないメソッドの戻り型としての使用です。考えてみれば理にかなっています。メソッドの戻り値の型がNothingであり、Nothingのインスタンスがまったく存在しない場合、そのようなメソッドは決して戻りません。

ロギングメソッドはUnitを返します。値Unitがあるため、実際に返すことができます。APIドキュメントから:

Unitはscala.AnyValのサブタイプです。タイプUnit()の値は1つだけであり、基になるランタイムシステムのオブジェクトによって表されません。戻り型がUnitのメソッドは、voidと宣言されているJavaメソッドに似ています。


2
おかげで、「二度と戻らない」とは、呼び出しが無期限にブロックされていることを意味します(たとえば、ジョブスケジューラの起動方法ですか?)
Sebastien Lorber

3
@Sabastien:正常に戻りません。例外をスローする可能性があります(james-iry.blogspot.com/2009/08/…を参照)。ブロッキング呼び出しが例外のスローのみで終了する場合は、カウントされます。質問に感謝します、これは明確にする必要がありました。
Nathan Hughes

18

あなたが引用した記事は誤解を招く可能性があります。Nullタイプは、互換性のためにそこにあるJava仮想マシン、特にJavaの。

Scalaを考慮しなければならない:

  • 完全にオブジェクト指向です:すべての値はオブジェクトです
  • 強く型付けされている:すべての値には型が必要です
  • nullJavaライブラリやコードなどにアクセスするための参照を処理する必要がある

したがってnullNull特性でありnull、唯一のインスタンスとして持つ値のタイプを定義する必要があります。

Null型システムであるか、コンパイラで開発している場合を除き、型で特に役立つものはありません。特にNull、メソッドの型パラメーターを定義する合理的な理由はわかりません。null


それは本当です、それで結局Nullの他の使用法はありませんか?
Sebastien Lorber 2013

@SebastienLorberが回答を編集しました。平均的な開発者の使用状況は実際にはわかりません。たぶん他の誰かが何か便利なものを考えることができます。
pagoda_5b 2013

これをありがとう。このようなことの理由を知っていれば理解し、そうでなければ記憶します。
Sreekar 2016

nullは、型パラメーターがあり、この質問と回答のように nullを返したい場合に役立ちます。スカラでnullを使用することは推奨されないため、型システムでも他の使用法がある可能性があります
Daniel Carlsson

15

Unit / Null / Nothingを戻り値の型以外に使用していますか?


Unit このように使用できます:

def execute(code: => Unit):Unit = {
  // do something before
  code
  // do something after
}

これにより、実行するコードの任意のブロックを渡すことができます。


Nullnull許容の任意の値のボトムタイプとして使用される場合があります。例はこれです:

implicit def zeroNull[B >: Null] =
    new Zero[B] { def apply = null }

Nothing の定義で使用されます None

object None extends Option[Nothing]

これにより、すべてを「拡張」するためNone、任意のタイプにを割り当てることができます。OptionNothing

val x:Option[String] = None

OK。Unitを使用する場合、コードブロックがユニット以外のものを返す場合に実行がこのジェネリック型を返すように、ジェネリック型を使用することができます。
Sebastien Lorber 2013

@drexinが別の回答のコメントで述べたように、これは主に副作用を示すために使用されます。
EECOLOR 2013

6

を使用する場合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]

1
また、EOption:共変な位置になければならないtrait Option[+E]ようなもの許可するval x: Option[Int] = None
vimの

5

私は実際にNullタイプを使用したことUnitはありませんが、Javaを使用する場合に使用しますvoidNothingNathanがすでに述べたように、のインスタンスは存在しない可能性があるため、は特別なタイプですNothingNothingいわゆるボトムタイプです。つまり、他のタイプのサブタイプです。これ(および反変型パラメーター)は、任意の値を先頭に追加できる理由です。NilこれはaでList[Nothing]あり、リストはこの要素型になります。Noneタイプの場合もOption[Nothing]。そのようなコンテナ内の値にアクセスしようとすると、例外がスローされます。これは、それがtypeのメソッドから戻る唯一の有効な方法だからですNothing


おかげでNoneがOption [Nothing]を拡張することを知りませんでした。サブタイプがNothingを使用できるいくつかのジェネリックの使用法では理にかなっています(NullとUnitの例を見つけるのは難しいと思います...)
Sebastien Lorber

ユニットが使用され、副作用が発生する場合。たとえば、IOモナドはIO[Unit]、コンソールなどに出力するタイプにすることができます。
drexin 2013

はい、決して使用しませんIOモナドをユニットで使用することは理にかなっています(そして、それが無限ストリームを生成するIO操作であれば何もないでしょうか?)
Sebastien Lorber 2013

いいえ、何も意味がありません。
drexin 2013

3

暗黙的に使用されることはほとんどありません。以下のコードでは val b: Boolean = if (1 > 2) false else throw new RuntimeException("error")else句のタイプはNothingで、ブール(およびその他のAnyVal)のサブクラスです。したがって、else句は実際には何も返しませんが、割り当て全体がコンパイラに有効です。


1

次にNothingfromの例を示しscala.predefます。

  def ??? : Nothing = throw new NotImplementedError

慣れていない場合(および検索エンジンで検索できない場合)???は、まだ実装されていないものに対するScalaのプレースホルダー関数です。コトリンのようにTODO

モックオブジェクトを作成するときに同じトリックを使用できますnotUsed。カスタムメソッドで未使用のメソッドをオーバーライドします。使用しないことの利点は???、実装するつもりのないものに対してコンパイル警告が表示されないことです。


0

カテゴリ理論の面では何もあり、最初のオブジェクトユニットがあるターミナルオブジェクト

https://en.wikipedia.org/wiki/Initial_and_terminal_objects

初期のオブジェクトはとも呼ばれcoterminalまたはユニバーサル、およびターミナルのオブジェクトはとも呼ばれ、最終的な

オブジェクトがinitialterminalの両方である場合、ゼロオブジェクトまたはnullオブジェクトと呼ばれます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.