すでに与えられた答えに加えて:
Option
タイプが常に唯一のオプションであるとは限りません。そして、ほとんどのインターフェースがを返すようにすることOption
は確かに望ましくありません。通常、呼び出し元がメソッドが「何も」を返さないことを期待できる場合にのみ望ましいです。
優れたAPIを設計するには、さらに検討が必要です。あなたの特徴とクラスを見てください。これまたはそのプロパティを提供できない場合、それらは完全ですか?-特定のプロパティがないと完全ではない場合、プロパティはOption
値であってはなりません。むしろ、次のように言うかもしれません。プロパティを提供できない場合、オブジェクトは別のタイプになります。
例として、ボードゲームのマップを表すグリッドについて考えてみます。Cell
すべてのフィールドはデータ型で表されます。一部のセルには色が付いている場合があります。
APIの最初のバージョンは次のようになります。
trait Cell {
def color:Color
}
さて、ある時点で、いくつかのセルに色がないことに気付くでしょう。たとえば、空のセル。または、デフォルトのGUIカラーでレンダリングされることになっているテキストのみを含むセル。
したがって、このバージョンを検討することになります。
trait Cell {
def color:Option[Color] = None
}
現在、必要に応じて、すべての実装でプロパティCell
を自由にオーバーライドできます。color
しかし、それが唯一の可能な解決策ではありません。
この代替案を考えてください:
trait Cell { }
trait ColoredCell extends Cell {
def color:Color
}
これで、セルのタイプによって色があるかどうかが決まり、色付きのセルには色が強制されます。
UIレイヤーの一部のコードには、次のようなフラグメントが含まれている可能性があります。
...
val cell:Cell = grid cellAt coordinates
val uiComponent:JComponent = ...
cell match {
case coloredCell:ColoredCell => uiComponent setColor coloredCell.color
case _ => // No color assigned
}
このアプローチは、不変オブジェクトで最適に機能します。それらは変更されることはなく、変更されたバージョンを表す新しいインスタンスを返します。
たとえば、すべてのセルに色を設定するメソッドがある場合があります。
trait Cell {
def withColor(color:Color):ColoredCell
}
このセルのコピーを表す新しいセルを別の色で返します。もちろん、これがのインスタンスになることはすでにわかっているColoredCell
ので、メソッドコントラクトに入れます。
このアプローチがうまく機能する場合もありますが、モデルにどの程度適合するかを事前に注意深く確認する必要があります。