【问题标题】:Is it possible to use the same class in different OCL packages?是否可以在不同的 OCL 包中使用相同的类?
【发布时间】:2017-12-09 17:15:29
【问题描述】:

我想使用 OCL 来链接在两个抽象级别上表示同一模型的两个类图。

为了说明,考虑一个抽象模型 A,它包含一个类 Person,它与自身有一个“父母”关联。还有一个更具体的模型 B,它具有 Person、Male 和 Female 类,其中 Male 和 Female 继承自 Person,以及两个关联,Person 和 Male 之间有一个“父亲”,Person 和女性之间有一个“Mother”。

我想使用 OCL 将两个模型链接在一起。也就是说,我想说具体模型中的“母亲”和“父亲”代表了抽象模型中的“父母”关联。

我知道可以将所有关联放在一个模型中,然后说类似

context Person inv:
 self.mother->forAll(m | m in self.parents) and
 self.father->forAll(f | f in self.parents) and
 self.parents->forAll(p | p in self.mother or p in self.mother)

但我特别想将模型分开。这个想法是具体模型不必显式地携带抽象。

我曾考虑使用包将每个模型放在单独的命名空间中,但据我所知,我最终得到了两个不同的 Person 类,每个包中都有一个。

有没有办法可以说不同包中的两个类名代表同一个类?那是同一组对象吗?例如,下面的表达式会实现这一点还是永远是假的?

Abstract::Person.allInstances() = Concrete::Person.allInstances()

【问题讨论】:

    标签: abstraction ocl


    【解决方案1】:

    我曾想过使用包将每个模型放在单独的命名空间中,但据我所知,我最终得到了两个不同的 Person 类,每个包中都有一个。

    没错。除非您定义了从 Abstract 包到 Concrete 包的包合并。

    包合并在 UML 的 12.2.3 节中定义:

    此功能旨在用于在 不同的包具有相同的名称,旨在代表 相同的概念(...)因此,对模型元素的任何引用 包含在接收包中意味着对结果的引用 的合并,而不是包含在其中的增量 包。 [UML 2.5]

    package Abstract
    context Person 
    inv: not self->closure(parent)->contains(self)
    
    package Concrete -- merges from package Abstract
    context Person
    inv: parents->asSet() = Set {mother, father}
    

    但是如果你将包Abstract 合并到包Concrete 中,那么Concrete::Person 会从Abstract::Person 带来parents,而你不希望这样。

    我特别想分离模型。这个想法是具体模型不必显式地携带抽象。

    请注意,一个实例不限于单个超类型,那么您可以指定每个Concrete::Person 是一个Abstract::Person,并且每个Abstract::Person 是一个Concrete::Person

    package Abstract 
    context Person inv: self->oclIsKindOf(Concrete::Person)
    
    package Concrete
    context Person 
    inv: self->oclIsKindOf(Abstract::Person) 
    inv: self->oclAsType(Abstract::Person).parents->asSet() = Set {mother, father}
    

    强制转换是必需的,因为Concrete::Person 不知道Abstract::Person 中的关联(它们是不同的类型,即使两者都应用于相同的实例)。

    另外,Concrete::Person 上的第一个不变量实际上是多余的,因为如果 self 不符合 Abstract::PersonoclAsType 将返回 invalid

    【讨论】:

    • 嗨哈维尔,感谢您的详细回答。我认为您的merge 方法最接近我想要的,但我认为oclIsKindOf 方法不会起作用,因为根据OCL 2.4 标准:oclIsKindOf 属性确定t是对象的直接类型或超类型之一。 换句话说,它是一个谓词,因此在不变量中使用它只会使不变量为假。
    • 如果Concrete::Person 不是Abstract::Person 实例的直接类型或超类型之一,则不变量为假...但我们已经说过Abstract::Person每一个实例也是Concrete::Person(因为是同一个概念),那么不变量永远为真;它的存在是为了要求模型是一致的。
    • 但是我们怎么说Abstract::Person 的每个实例也是Concrete::Person 呢?是用 OCL 表达式说的吗?还是我们只是在正式框架之外这么说?
    • self->oclIsKindOf(Concrete::Person)Abstract::Person 的不变量
    • 所以我在不变量中写的任何东西都会变成真的?
    【解决方案2】:

    (RSS 提示这是一个新话题!)

    问题是您的抽象/具体变体在某种意义上是不同的类,但在另一种意义上是相同的类。因此,您必须根据消费者是否希望将抽象/具体视为不同/相同的类来划分消费者,并为每个消费者定义“相同”的含义。

    对于人类,您可以使用拼写约定使不同的类“相同”。或注释或无数 UML 关联。

    如果您希望某种程度的功能相同,允许在某些模拟中互换使用“抽象”/“具体”类,您可能需要“抽象”和具体类都从您具有不同的共享接口继承抽象'/'具体'的实现。

    如果出于文档目的使用相同性,您可以考虑使用一种模型转换语言,将一种语言转换为另一种语言。许多M2M实际上只是OCL的一种外部语言,为模型导入/导出和变异提供支持。 M2M 可以捕获与“抽象”和“具体”相关的常规习语,并且可能适用于数学证明和/或自动代码生成。它当然应该满足需求跟踪的必要性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-15
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 2012-02-08
      相关资源
      最近更新 更多