値オブジェクト

コンピュータサイエンスにおいて値オブジェクト（あたいオブジェクト、）は、同一性が識別子でなく属性によって決定されるオブジェクトのことをいう。異なるオブジェクトであっても、それらを構成する値が等価であればそれらは等価であると見做される。

値オブジェクトで表せるものとしては、数や色、日付、金額、文字列等が挙げられる。

値オブジェクトはイミュータブルであることが望ましいとされる。これは、等価なものとして生成されたオブジェクトは必ず等価性を維持することが期待されるためである。加えて、オブジェクトがイミュータブルであることによって、利用者側が一度生成されたオブジェクトを無効な状態へ変更することを防ぎ、クライアントコードにおけるバギーな挙動を防ぐことができるとされる。

これらの特徴により、概念的には等価である複数のオブジェクトを値オブジェクトとして得ることができる。値オブジェクトが用いられるような対象においては、単一のインスタンスの参照を使い回すよりは、新しいオブジェクトを生成する方が簡単な場合が多い。

値オブジェクトは、ドメイン駆動設計におけるドメインモデルの構成要素の1つでもある。

 定義 
ダーク・リールら（1988）は、値（Value）について、以下の四つの主要な性質を持つものとした。

リールらは、この「値」を表現するはプログラミング言語においてプリミティブ型として提供され、言語としての用意がない場合はこれをクラスで実装する必要があるものとした。

 実装 
値オブジェクトは一般に等価性を判定するメソッドを持つ。例えばPythonの整数型であれば、__eq__()メソッドを持つ。

さまざまなオブジェクト指向プログラミング言語のニュアンスにより、それぞれに値オブジェクトを実装および使用するための独自のメソッドとパターンがある。

 C＃ 
C＃では、クラスは参照型であり、構造体（ C言語の構造体から派生した概念）は値型である 。したがって、クラス定義から派生したインスタンスはオブジェクトであり、構造体定義から派生したインスタンスは値オブジェクトと呼ばれる（正確には、構造体をイミュータブルにして、属性を読み取り専用として宣言する事で値オブジェクトを表現することができる ）。

次の手順を実行することによって、C#クラスを値オブジェクトとして扱うことができる。

 をオーバーライドして、オブジェクトがビジネスロジックを使用して比較されることを保証する。
 メソッドが使用されるように、デフォルトの動作およびを演算子オーバーロードする。
  メソッドをオーバーライドして、等価性を持つオブジェクトのハッシュが同じとなるようにする。
 プロパティセッターを削除し、コンストラクターを介してのみメンバー値を渡すことにより、クラスを不変にする 。

あるいは、C# 9.0で追加されたレコードも値オブジェクトとなる型の作成に使用できる。

 C++ 
C++では、代入演算子をオーバーロードし、フィールド（コンストラクターの初期化子リストによって一度だけ評価される）とクラスのメソッドに適切なconst制約を使用することで値オブジェクトを構築できる。

ただし、フィールド自体をconstとして宣言した場合（つまり非constフィールドとgetterの組み合わせで実現する方法でなかった場合）、そのような値オブジェクトは別の値オブジェクトで完全に上書きすることは不可能となる（  ）。

 Java 
C＃やC++とは異なり、Javaは言語レベルでのカスタム値型をサポートしていない。カスタム値型のサポートの拡張は検討されているが、すべてのカスタム型は参照型であるため、同一性と参照のセマンティクスを持つ。 

したがって、Javaプログラマは、イミュータブルなオブジェクトを作成することによって値オブジェクトをエミュレートする事になる。オブジェクトの状態が変わらない限りにおいて、参照を渡すことは、値オブジェクトをコピーすることと意味的に同等となるからである。

すべての属性を空白のfinal hence assignable only in the constructorsとして宣言し、すべての属性をまたはのような可変タイプのような可変タイプではなく不変タイプ（たとえば、、、またはこれらの規則に従って宣言された他のタイプ）とする。また、参照ではなく値を比較するために、equalsとhashCodeを定義するべきである。

「VALJO」（VALue Java Object）という用語は、正しく定義されたイミュータブルなあたいオブジェクトに必要な、より厳密なルールのセットを指すために作られた。

値オブジェクトは、Java14以降データレコードとして使用可能である。

 例 
public class StreetAddress
{
    public StreetAddress(string street, string city)
    {
        Street = street;
        City = city;
    }

    public final string Street { get; }
    public final string City { get; }
}

 関連項目 
 データ転送オブジェクト
 ドメイン駆動設計
 値 (計算機科学)


 脚注 

Category:オブジェクト (計算機科学)