1. 概要

このチュートリアルでは、Scalaの Nil、Null、Nothing、Unit、タイプとNoneタイプの違いを示します。

これらのキーワードはすべて、値がないことを表すために使用されているように見えるかもしれませんが、それぞれに独自の目的があります。

それぞれについて説明し、例と使用例を使用してその特性を学習します。

2. Nullおよびnull

null 参照は、存在しない値を表すために使用され、大文字の「N」を持つNullがそのタイプです。

2.1. nullリファレンス

最初にnull参照から始めましょう。これは、恐ろしい NullPointerException が原因で、おそらく私たちのほとんどにとって最も馴染みのある参照です。

nullは、オブジェクトを参照していない参照の値です。 これは、すべての参照タイプ、つまりscala.AnyRefを拡張するすべてのタイプの代わりに使用できます。

null参照を使用してクラスを初期化する例を見てみましょう。

case class Car(make:String)

//Initializes an instance of Car with null reference
val nullRefCar:Car = null
try{
  println(nullRefCar.make)
}catch{
  case npe:NullPointerException => println("Null Pointer Error occurred: %s".format(npe))
}

//Initializes an instance of Car type with argument as null
val nullMakeCar = Car(null)
println(nullMakeCar.make)

Nil など、変数の型の空の値が使用可能な場合は、変数の初期化中にnullを使用しないようにする必要があります。

また、 null 参照を返す代わりに、空の結果を返す可能性のある関数にはオプションタイプを使用することをお勧めします。

2.2. Nullタイプ

Null は、null参照のタイプです。 これは、私たちが定義するカスタムクラスと特性を含むすべての参照タイプを拡張します。 これにより、任意の参照型の代わりにnull値を使用できます。

Null タイプには、メソッドまたはフィールドがありません。 抽象最終クラスとして定義されているため、拡張またはインスタンス化することはできません。 nullは、タイプNullの唯一のインスタンスです。

3. Nil –空のリスト

Nilは、リストタイプを拡張する空のシングルトンオブジェクトリストです。したがって、他の List オブジェクトが持つすべてのフィールドとメソッドがあり、通常、空のリストを初期化するために使用されます。

val myList = Nil
println("a list is initialized with length %s".format(myList.length))

すべてのListメソッドは、Nilにも適用できます。 したがって、通常のリストの代わりに安全に使用できます。 新しいリストを作成して入力する一般的な方法は、 Nilcons(::)演算子を使用することです。

val consList = "A" :: "B" :: Nil

4. なし–空のオプション

なしはオプションタイプのサブタイプです。 関数が返す値がない場合にnull値を返すときに発生する問題を確認しました。 これにより、 null を適切に処理しない場合、呼び出し側プログラムがクラッシュする可能性があります。

Scalaのベストプラクティスでは、関数に戻り値がない場合に備えて、戻り値をOptionタイプでラップすることをお勧めします。

ロール番号を渡して生徒の名前を取得する関数の例を見てみましょう。

val studentRegister:Map[Int,String] = Map(1 -> "John", 2 -> "Mary")

def getStudentName(studentRegister:Map[Int,String], roll:Int):Option[String] = {
  studentRegister.get(roll)
}

def printStudent(student:Option[String]): Unit = {
  student match {
    case Some(str) => println("Student Name is %s".format(str))
    case None      => println("No Student!!")
  }
}

ロール番号がレジスターで使用できない場合、関数は None を返し、呼び出し元のメソッドはレコードが欠落している場合を適切に処理できます。

5. Unit –空の返品タイプ

Unitは、何も返さない関数の戻りタイプです。 これは、Javaの void 型と同じですが、1つの違いがあります。Scalaの Unit型には()というシングルトン値が1つありますが、Javaのvoidには値がありません:

def functionReturnUnit:Unit = {
  """
    do something, don't return anything
  """
}
println("result of function returning Unit: %s".format(functionReturnUnit))

コンソールに「関数が単位を返す結果:()」として出力が出力されます。

関数定義で戻り型と“ =” 演算子を省略した場合、Scalaコンパイラーは暗黙的にそれをUnit戻り型に変換します。

def functionReturnImplicitUnit {
  """
    do something
  """
}

6. なし

Scalaの絶対的な「値なし」タイプはありません。メソッドや値はありません。

AnyタイプはScala型システム全体のルートであり、Anyタイプを拡張するものはありません。したがって、参照型と値型の両方のScala型の代わりにNothingを使用できます。

Nullタイプと一緒にタイプ階層の最下部にあるものはありません。 したがって、これはScalaの他のすべてのタイプのサブタイプでもあり、私たちが定義するクラスや特性でさえもです。 このプロパティは、一般的な空の基本クラスを定義するなどの状況で多くの利点を提供します。 Nilはそのような例です。 、 Int 、またはカスタムクラス。

使えない何もない関数が例外をスローする場合を除いて、関数の戻り型としてそれの訳は何も価値がない 。 そのようなユースケースの1つは、例外をログに記録し、別のカスタム例外をスローする関数です。

def logException(e:Exception):Nothing = {
  println("logging Exception: %s".format(e.getMessage))
  throw new Exception("My New Exception")
}

7. 結論

このチュートリアルでは、一連の簡単な例を使用して、Scalaで無を表すための6つのエンティティを調べました。 それぞれの特徴と振る舞い、そしてそれらのアプリケーションについて学びました。 次に、nullを返す代わりにOptionを使用したり、 Nil を使用してリストを初期化したりするなど、いくつかのベストプラクティスを理解して結論を出しました。 。

いつものように、記事の完全なソースコードは、GitHubから入手できます。