ラッパー用に余分なメモリを消費しないオプションを実装しようとしています。クラスを作成します。Null は None を表し、null 以外の値は Some を表します。
class Maybe[+T](private val nullable: T) extends AnyVal {
@inline final def isDefined: Boolean = {
println("isDefined called")
val res = nullable != null
println(s"result = $res")
res
}
@inline final def get: T = if (isDefined) nullable else throw new NoSuchElementException
@inline final def getOrElse[B >: T](default: => B): B = if (isDefined) this.get else default
@inline final def map[B](f: T => B) : Maybe[B] = if (isDefined) Maybe.some(f(this.get)) else Maybe.none
@inline final def flatMap[B](f: T => Maybe[B]): Maybe[B] = if (!isDefined) Maybe.none else f(get)
def toOption : Option[T] = if (isDefined) Some(get) else None
}
object Maybe {
def some[T](value:T) : Maybe[T] = new Maybe(value)
final val none : Maybe[Nothing] = {
println("start initializing none")
val v = new Maybe(null)
println("1")
val res = v.asInstanceOf[Maybe[Nothing]]
println("2")
res
}
}
object MaybeTest extends App {
println("try to create Maybe.none")
val myNone = Maybe.none
println("Initialized")
println(myNone.isDefined)
println("Accessed")
}
しかし、実行しようとすると、NPE が表示されます。
Maybe.none を作成してみる
なしの初期化を開始
1
2
初期化済み
スレッド「メイン」での例外 java.lang.NullPointerException at com.MaybeTest$.delayedEndpoint$com$MaybeTest$1(Maybe.scala:34) at com.MaybeTest$delayedInit$body.apply(Maybe.scala:30) at scala. Function0$class.apply$mcV$sp(Function0.scala:34) で scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) で scala.App$$anonfun$main$1.apply(App. scala:76) で scala.App$$anonfun$main$1.apply(App.scala:76) で scala.collection.immutable.List.foreach(List.scala:392) で scala.collection.generic.TraversableForwarder$class で.foreach(TraversableForwarder.scala:35) で scala.App$class.main(App.scala:76) com.MaybeTest$.main(Maybe.scala:30) で com.MaybeTest.main(Maybe.scala)
「extends AnyVal」を削除すると、すべて正常に動作します。誰かがそのような行動を説明できますか?