This article has an English version available.

对象中成员变量的角色

下面用一个典型的类定义来展示成员变量的不同角色:

python
class Parent:
    # 配置
    feature_a_flag: bool

    # 借用资源
    """这是一个用于发起 HTTP 请求的客户端。
    它在全局初始化,
    并在程序中被所有对象共享。"""
    client: Client

    # 自有资源
    """这是一个数据库连接。
    我们需要调用 `connect()` 才能开始使用它。
    用完之后需要调用 `close()`。"""
    conn: Connection

    # 状态
    last_modified_time: float

    # 子对象
    child: List[Child]

配置(Config)

配置相对简单。它通常是原始值,比如字符串、数字、布尔值等,或是由原始值组成的结构(例如 JSON 风格的对象)。

配置是只读的,运行时不会改变,通常在构造函数中初始化。

由于它是只读的,所以可以安全地在对象之间共享,比如传给其他对象的构造函数。

而且由于它是原始值,我们不用担心内存管理问题,直接传递给 GC 处理即可。

借用资源(Borrowed resources)

借用资源通常在多个对象之间共享。它可能在全局初始化后被所有对象共享,也可能在某个对象中初始化后被其他对象借用。

当一个对象从另一个对象借用资源时,它并不拥有该资源,因此不需要调用 close() 来销毁它。

但是它必须确保自己使用该资源时该资源仍然可用,也就是说它的生命周期必须在资源拥有者的生命周期之内。拥有者必须在借用者存活期间保持存活,而借用者必须在拥有者销毁之前被销毁。

自有资源(Owned resources)

如前所述,拥有资源意味着对象要对资源的生命周期负责,需要调用 close() 来销毁它。

状态(States)

“状态”可以包含构成对象的一切信息,但这里我们将其定义为自有资源的一个子集:它由对象拥有,且不与其他对象共享。

状态只服务于对象本身,并且会被对象的方法频繁修改。相比之下,配置与资源通常在构造函数中设置,并在之后很少改变。

即便我们调用资源的可变方法,也是在改变资源自身的状态,而不是对象本身的状态。

你可能会注意到,自有资源的状态也是对象状态的一种。但为了清晰起见,我们仍把它们分开,这是“子状态”。

子对象(Children objects)

子对象也可以被视为一种自有资源或状态。父对象需要负责它们的生命周期。

子对象可以拥有自己的状态,而这些状态如上所述是父对象的子状态。

子对象可以拥有自己的资源,也可以从父对象借用资源。这很自然,因为它的生命周期由父对象管理,因此天然处于父对象生命周期之内。