第 5 章

定义属性:更多细节

标签挂多高是门学问;填一次、两边自动更新

这一章讨论定义属性时(第 3 章的第 5、6 步)还需要留心的几个细节,主要是逆属性和属性的默认值。

5.1互为逆属性

一个属性的值可能取决于另一个属性的值。 比如,如果一款酒是由某家酒庄生产的,那么这家酒庄就生产这款酒。maker(生产者)和 produces(生产)这两个关系,叫做互为逆关系(inverse relations)。

把信息“两个方向都存一遍”是冗余的。 当我们知道一款酒是由某家酒庄生产的,使用知识库的应用总能推断出逆关系的值——即这家酒庄生产了这款酒。

不过,从知识获取(knowledge-acquisition)的角度看,两个方向的信息都显式可用会更方便:这样用户可以在一个场合填酒,在另一个场合填酒庄,而知识获取系统可以自动补上逆关系的值,从而保证知识库的一致性。

本书的例子有一对逆属性:Wine 类的 maker 属性,和 Winery 类的 produces 属性。当用户创建一个 Wine 类的实例并填上 maker 属性的值时,系统自动把新建的这个实例加进对应 Winery 实例的 produces 属性里。比如,当我们说 Sterling Merlot 是由 Sterling Vineyard 酒庄生产的,系统会把这个酒自动加进 Sterling Vineyard 酒庄所生产的酒的列表里(图 9)。

原书图 9:逆属性
原书图 9:带逆属性的实例。Winery 类的 produces 属性是 Wine 类的 maker 属性的逆属性。填其中一个属性会触发另一个的自动更新。
🍷 Sterling Merlot 填:maker = Sterling Vineyards 只填了一次 ✍️ 自动同步 ⚡ 🏰 Sterling Vineyards produces 清单自动 + 这瓶酒 两个方向都查得到 ✅
你只填了一次,两个地方都更新了。
〔说人话〕看图 9 的两条黑箭头:
· 上面一条从 Sterling Merlot 窗体的 Name 框,指向 Sterling Vineyards 窗体的 Name 框。含义是:当你在酒那边填了“生产者 = Sterling Vineyards”……
· 下面一条从 Sterling Vineyards 窗体的 Produces 列表(第一项 Sterling Merlot 已高亮),指回上面的 Sterling Merlot。含义是:……系统自动把这个酒加进了酒庄的生产清单。

你只填了一次,两个地方都更新了。 这就是逆属性的全部价值:数据只录一遍,但两个方向都能查。

5.2默认值

很多基于框架的系统允许为属性指定默认值(default value)。 如果某个属性值对某个类的大多数实例都相同,我们就可以把这个值定义为该属性的默认值。之后,每当创建这个类的一个新实例,系统会自动填入这个默认值。我们之后可以把它改成约束所允许的任何其他值。也就是说,默认值是为了方便而存在的:它们不对模型施加任何新的限制,也不以任何方式改变模型。

比如,如果我们要讨论的绝大多数酒都是酒体饱满的,我们可以把 full 设为 body 属性的默认值。那么,除非另有说明,我们定义的所有酒都会是酒体饱满的。

默认值 ≠ 属性值

注意,这和“属性值”(slot value)是两回事。 属性值不能改。 比如,我们可以说 Dessert wine 类的 sugar 属性的值是 SWEET。那么 Dessert wine 类的所有子类和实例,sugar 属性的值都会是 SWEET。这个值在任何一个子类或实例里都不能被改掉。

默认值(default)属性值(slot value)
填不填自动填上自动填上
能不能改能,随便改不能,改了就是建模错误
本质一个偷懒用的初始值一条绑死逻辑的约束
例子body 默认 full——博若莱可改成 LIGHT甜酒的 sugar = 甜。这不是偏好,是定义
〔说人话〕两者的区别是“默认”和“强制”。

例子对照:body 的默认值 full——大部分酒是饱满的,但博若莱可以改成 LIGHT;Dessert wine 的 sugar = SWEET——甜酒的糖分必须是甜,这不是偏好,是定义。
← 上一章 下一章:命名约定 →