计算机科学裡的值物件(value object)是表示簡單實體的小型物件,這類實體的相等只根據其值,不依照其身份英语Identity (object-oriented programming),只要兩個值物件的值相等,即視為相等,這兩個物件不需是同一個物件[1][2]

值物件的例子像是錢的總金額,以及日期範圍等。

值物件很小,因此可以將值物件複制數份,而這些值物件表示的是同一個實體,對於值物件,創建一個新物件會比只有一個實例,其他部份再參考此一實例要簡單[2]

值物件需是不可變物件[3]:因為值物件的定義中隱含一件事,若兩個值物件相等,他們就需一直維持相等。讓值物件是不可變的也有其優點,因為客戶端的程式無法將值物件改為無效的狀態,或是在初始化後進行不正確的操作[4]

值物件常見於領域驅動設計(DDD)的建構模塊中。

實現

编辑

由於各種物件導向程式语言之間有細微的差異,田此各語言在實現值物件和使用值物件上,都有自的方式以及设计模式

C#

编辑

C#裡,類別屬於引用類型,而結構體(概念源自C語言的结构体)是值類型[5]。 因此衍生自類別定義的實例是物件,而衍生自結構體定義的則是值物件(更準確的說法,結構體可以宣告屬性readonly,使結構體不可變,因而成為值物件 [6])。

以下的作法可以在C#類別中加入值物件的性質:

  1. 重載Object.Equals方法,確保物件比較時是比較业务逻辑,不是其身份。
  2. 运算符重载==!=的預設行為,使用Equals方法。
  3. 重載Object.GetHashCode方法,確保兩個相等的物件有相同的hash。
  4. 透過移除屬性setter,以及只從創建子傳遞成員的值的方式,讓類別不可變[7][8]

範例:

public record StreetAddress(string Street, string City);

或是以下更多行的例子

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

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

C++

编辑

C++裡的值物件可以用設定運算子重載,再使用適當的常數限定符在欄位上(這樣就只會在創建時設定一次),以及類型的方法上。

不過,若欄位本身宣告為const,會有副作用,無法用另一個物件完全覆寫(object1 = object2)。若是用const以外的欄位,但是只開放getter存取函式,以此方式實現值物件,就可以做到用另一個物件完全覆寫的功能。

Python

编辑

Python有資料類別可以提供相關測試,並且可以用frozen參數設為不可變[9]

from dataclasses import dataclass

@dataclass(frozen=True)
class StreetAddress:
    """Represents a street address."""

    street: str
    city: str

Java

编辑

值物件在Java 14起開始支援,是data record[10]

Java和C#和C++不同,其沒有在語言層面支援自定義型態,每一個自定義型態都是參考性能,因此也會有身份和參考語意[11],不過仍有人在考慮如何支援自定義的值物件[12]

因此Java程式設計者會創建不可變的物件來模擬值物件[13],若物件的狀態不會變化,傳參考在語意上和複製值物件一樣。

可以將類別的所有屬性宣告為blank final,[14],宣告其中所有的屬性都是不可變的型態(例如,或是依照其規則宣告的其他型態),不能使用像是ArrayList甚至是Date的可變形態。也需要定義equals和hashCode,以其值進行比較,而不是使用參考。

已有人用VALJO(VALue Java Object)一詞來指正確定義地不可變值物件,需要符合的較嚴格規則[15]

public class StreetAddress {
    public final String street;
    public final String city;

    public StreetAddress(String street, String city) {
        this.street = street;
        this.city = city;
    }
    public boolean equals(StreetAddress that) {
        return getClass()==that.getClass() && street==that.street && city==that.city;
    }
    public int hashCode() {
        return Objects.hash(street, city);
    }
}

上述的程式,到Java 14就變簡單了。

public record StreetAddress (String street, String city) {}

Kotlin

编辑
data class StreetAddress(val street: String, val city: String)

Kotlin裡,任何型態都可以有構造器shortcut在其型態本身之前(若該型態有本身的話),一方面是宣告欄位,也是設定這些欄位的值。若加上data關鍵字,就會用值物件的邏輯來實現equals和hashCode等。

Ruby

编辑

Ruby可以用Data.define類別來支援值物件(自Ruby 3.2導入),自動提供equality、hashing和 immutability.[16]

StreetAddress = Data.define(:street, :city)

相關條目

编辑

參考資料

编辑
  1. ^ Fowler, Martin. Value Object. Catalog of Patterns of Enterprise Application Architecture. Martin Fowler (martinfowler.com). 2003 [17 July 2011]. (原始内容存档于2025-12-04). 
  2. ^ 2.0 2.1 Value Object. Portland Pattern Repository's Wiki. Cunningham & Cunningham, Inc. (c2.com). [6 September 2012]. (原始内容存档于2011-07-22). 
  3. ^ Value Object Should be Immutable. Portland Pattern Repository's Wiki. Cunningham & Cunningham, Inc. (c2.com). [6 September 2012]. (原始内容存档于2012-06-09). 
  4. ^ Burns, Sam. The Value of a Value Object. sam-burns.co.uk. 原始内容存档于April 19, 2015. 
  5. ^ Classes and Structs (C# Programming Guide). Microsoft Developer Network (msdn.microsoft.com). 2012 [5 September 2012]. (原始内容存档于2017-02-03). 
  6. ^ Creating an immutable value object in C# - Part III - Using a struct. Luca Bolognese's WebLog. 2012 [7 September 2012]. (原始内容存档于2012-09-25). 
  7. ^ Koirala, Shivprasad. Immutable objects in C# - CodeProject. www.codeproject.com. [2017-12-26]. (原始内容存档于2025-07-16). 
  8. ^ koirala, Shivprasad. Value Object Design Pattern in C#. www.codeproject.com. [2017-12-26]. (原始内容存档于2025-07-10). 
  9. ^ dataclasses — Data Classes. Python documentation. [7 June 2023]. (原始内容存档于2026-01-30). 
  10. ^ Records Come to Java. [13 April 2021]. (原始内容存档于2021-08-02). 
  11. ^ Java Language Specification, chapter 4. Types, Values, and Variables. [7 October 2015]. 
  12. ^ JEP 169: Value Objects. [7 October 2015]. (原始内容存档于2022-05-21). 
  13. ^ Immutable objects. Collected Java Practices. 2012 [5 September 2012]. (原始内容存档于2025-12-31). 
  14. ^ 只有在构造器裡才能設定
  15. ^ VALJOs - Value Java Objects. [19 October 2014]. (原始内容存档于2014-05-09). 
  16. ^ Class: Data. Ruby documentation. [29 September 2025]. (原始内容存档于2025-12-31). 

📚 Artikel Terkait di Wikipedia

Kotlin

buildString() { append(this@andAnother); append(" "); append(other ?: "") } //immutable types, delegated properties, lazy initialization, string templates val

值类型与引用类型

undefined, null objects (including functions, arrays, typed arrays, sets, maps, weak sets and weak maps) OCaml immutable characters, immutable integer numbers

演员模型

每个Eval消息都有一个充当环境的演员的地址,它能够进行标识符与值的绑定(binding)。environment演员是不可变的(immutable),也就是不变更的。 当一个environment演员收到Request[Bind[identifier value]

日本近代科技发明列表

UK. [2015-05-19]. (原始内容存档于2017-10-16).  Sugai, Philip (2010), The Six Immutable Laws of Mobile Business, ISBN 978-0471741466, pg.26. Docomo's Service