如何在Enterprise Architect中更改父类时更新子类

时间:2014-06-17 11:32:11

标签: oop abstract-class enterprise-architect

我想在实现继承的 Enterprise Architect(版本10.0)中创建一个类图。我添加一个抽象类,然后创建3个实现抽象类的类 现在,如果我在抽象类中进行一些更改,子类不会更改。 (例如,为抽象类添加另一个方法,但是子类不具有此方法) 当父类更改时,如何更新(或刷新)子类?

3 个答案:

答案 0 :(得分:3)

选择课程,然后按Ctrl + Shift + o进行刷新。但是,这不会执行完全刷新,因此您需要删除旧版本的操作等,但EA将显示覆盖方法对话框。

答案 1 :(得分:2)

您可以使用我的插件EA-Matic来执行此操作。

EA-Matic捕获Enterprise Architect中的加载项事件,并将它们转发给内置脚本环境。

这允许创建具有完整加载功能的脚本,同步覆盖只是可能的应用程序之一。

我编写的用于演示加载项的示例脚本之一正是这样做的:Automatically synchronize overrides in Enterprise Architect with EA-Matic

此示例脚本使用事件EA_OnContextItemChanged来存储所选操作的覆盖

'Event Called when a new element is selected in the context. We use this operation to keep the id of the selected operation and a list of its overrides
'Because now is the only moment we are able to find it's overrides. Once changed we cannot find the overrides anymore because then they already
'have a different signature
function EA_OnContextItemChanged(GUID, ot)
    'we only want to do something when the selected element is an operation
    if ot = otMethod then
        'get the model
        dim model
        set model = getEAAddingFrameworkModel()
        'get the operation
        dim operation
        set operation = model.getOperationByGUID(GUID)
        'remember the operationID
        operationID = operation.id
        'remember the overrides
        set overrides = getOverrides(operation, model)
        Repository.WriteOutput "EA-Matic", overrides.Count & " overrides found for: " & operation.name,0
    end if
end function

EA_OnNotifyContextItemModified修改替换,以防更改内容。

'Event called when an element is changed. Unfortunately EA doesn't call it for an operation, only for the owner so we have to work with that.
function EA_OnNotifyContextItemModified(GUID, ot)
    'we only want to do something when the selected element is an operation
    if ot = otElement then
        'get the operation
        'Here we use the EA API object directly as most set methods are not implemented in EA Addin Framework
        dim wrappedOperation
        set wrappedOperation = Repository.GetMethodByID(operationID)
        dim modifiedElement
        set modifiedElement = Repository.GetElementByGuid(GUID)
        if not wrappedOperation is Nothing and not modifiedElement is Nothing then
            'check to be sure we have the same operation
            if modifiedElement.ElementID = wrappedOperation.ParentID AND overrides.Count > 0 then
                dim synchronizeYes
                synchronizeYes = MsgBox("Found " & overrides.Count & " override(s) for operation "& modifiedElement.Name & "." & wrappedOperation.Name & vbNewLine & "Synchronize?" _
                                        ,vbYesNo or vbQuestion or vbDefaultButton1, "Synchronize overrides?")
                if synchronizeYes = vbYes then
                    synchronizeOverrides wrappedOperation
                    'log to output

                    Repository.WriteOutput "EA-Matic", "Operation: " & wrappedOperation.name &" synchronized" ,0
                end if
                'reset operationID to avoid doing it all again
                operationID = 0
            end if
        end if
    end if
end function

在OnContextItemChanged中,它首先通过查询从模型中选择具有相同签名的所有操作来获取覆盖。

'gets the overrides of the given operation by first getting all operations with the same signature and then checking if they are owned by a descendant
function getOverrides(operation, model)
    'first get all operations with the exact same signature
    dim overrideQuery
    overrideQuery = "select distinct op2.OperationID from (((t_operation op " & _
                    "inner join t_operation op2 on op2.[Name] = op.name) "& _
                    "left join t_operationparams opp on op.OperationID = opp.OperationID) "& _
                    "left join t_operationparams opp2 on opp2.OperationID = op2.OperationID) "& _
                    "where op.OperationID = "& operation.id &" "& _
                    "and op2.ea_guid <> op.ea_guid "& _
                    "and (op2.TYPE = op.Type OR (op2.TYPE is null AND op.Type is null)) "& _
                    "and (op2.Classifier = op.Classifier OR (op2.Classifier is null AND op.Classifier is null)) "& _
                    "and (opp.Name = opp2.Name OR (opp.Name is null AND opp2.Name is null)) "& _
                    "and (opp.TYPE = opp2.TYPE OR (opp.TYPE is null AND opp2.Type is null)) "& _
                    "and (opp.DEFAULT = opp2.DEFAULT OR (opp.DEFAULT is null AND opp2.DEFAULT is null)) "& _
                    "and (opp.Kind = opp2.Kind OR (opp.Kind is null AND opp2.Kind is null)) "& _
                    "and (opp.Classifier = opp2.Classifier OR (opp.Classifier is null AND opp2.Classifier is null)) "
    dim candidateOverrides
    set candidateOverrides = model.ToArrayList(model.getOperationsByQuery(overrideQuery))
    'then get the descendants of the owner
    dim descendants
    dim descendant
    'first find all elements that either inherit from the owner or realize it
    dim owner
    set owner = model.toObject(operation.owner)
    set descendants = getDescendants(owner, model)
    'then filter the candidates to only those of the descendants
    'loop operations backwards
    dim i
    for i = candidateOverrides.Count -1 to 0 step -1
        dim found
        found = false
        for each descendant in descendants
            if descendant.id = model.toObject(candidateOverrides(i).owner).id then
                'owner is a descendant, operation can stay
                found = true
                exit for
            end if
        next
        'remove operation from non descendants
        if not found then
            candidateOverrides.RemoveAt(i)
        end if
    next
    set getOverrides = candidateOverrides
end function

然后我们操作所有者的所有后代(递归地)并将操作过滤为仅由后代拥有的操作。

'gets all descendant of an element. That is all subclasses and classes that Realize the element.
'Works recursively to get them all.
function getDescendants(element, model)
    dim descendants
    dim getdescendantsQuery
    getdescendantsQuery = "select c.Start_Object_ID as Object_ID from (t_object o " _
                    & "inner join t_connector c on c.End_Object_ID = o.Object_ID) " _
                    & "where "_
                    & "(c.[Connector_Type] like 'Generali_ation' "_
                    & "or c.[Connector_Type] like 'Reali_ation' )"_
                    & "and o.Object_ID = " & element.id
    set descendants = model.toArrayList(model.getElementWrappersByQuery(getdescendantsQuery))
    'get the descendants descendants as well
    dim descendant
    dim descendantsChildren
    for each descendant in descendants
        if IsEmpty(descendantsChildren) then
            set descendantsChildren = getDescendants(descendant, model)
        else
            descendantsChildren.AddRange(getDescendants(descendant, model))
        end if
    next
    'add the descendantsChildren to the descendants
    if not IsEmpty(descendantsChildren) then
        if  descendantsChildren.Count > 0 then
            descendants.AddRange(descendantsChildren)
        end if
    end if
    set getDescendants = descendants
end function

最后,它使用以下函数同步操作

'Synchronizes the operation with it's overrides
function synchronizeOverrides(wrappedOperation)
    dim override
    for each override in overrides
        dim wrappedOverride
        set wrappedOverride = override.WrappedOperation
        'synchronize the operation with the override
        synchronizeOperation wrappedOperation, wrappedOverride
        'tell EA something might have changed
        Repository.AdviseElementChange wrappedOverride.ParentID
    next
end function

'Synchronizes the operation with the given override
function synchronizeOperation(wrappedOperation, wrappedOverride)
    dim update
    update = false
    'check name
    if wrappedOverride.Name <> wrappedOperation.Name then
        wrappedOverride.Name = wrappedOperation.Name
        update = true
    end if
    'check return type
    if wrappedOverride.ReturnType <> wrappedOperation.ReturnType then
        wrappedOverride.ReturnType = wrappedOperation.ReturnType
        update = true
    end if
    'check return classifier
    if wrappedOverride.ReturnType <> wrappedOperation.ReturnType then
        wrappedOverride.ReturnType = wrappedOperation.ReturnType
        update = true
    end if
    if update then
        wrappedOverride.Update
    end if
    'check parameters
    synchronizeParameters wrappedOperation, wrappedOverride
end function

'Synchronizes the parameters of the given operatin with that of the overrride
function synchronizeParameters(wrappedOperation, wrappedOverride)
    'first make sure they both have the same number of parameters
    if wrappedOverride.Parameters.Count < wrappedOperation.Parameters.Count then
        'add parameters as required
        dim i
        for i = 0 to wrappedOperation.Parameters.Count - wrappedOverride.Parameters.Count -1
            dim newParameter
            set newParameter = wrappedOverride.Parameters.AddNew("parameter" & i,"")
            newParameter.Update
        next
        wrappedOverride.Parameters.Refresh
    elseif wrappedOverride.Parameters.Count > wrappedOperation.Parameters.Count then
        'remove parameters as required
        for i = wrappedOverride.Parameters.Count -1 to wrappedOperation.Parameters.Count step -1
            wrappedOverride.Parameters.DeleteAt i,false
        next
        wrappedOverride.Parameters.Refresh
    end if
    'make parameters equal
    dim wrappedParameter
    dim overriddenParameter
    dim j
    for j = 0 to wrappedOperation.Parameters.Count -1
        dim parameterUpdated
        parameterUpdated = false
        set wrappedParameter = wrappedOperation.Parameters.GetAt(j)
        set overriddenParameter = wrappedOverride.Parameters.GetAt(j)
        'name
        if overriddenParameter.Name <> wrappedParameter.Name then
            overriddenParameter.Name = wrappedParameter.Name
            parameterUpdated = true
        end if
        'type
        if overriddenParameter.Type <> wrappedParameter.Type then
            overriddenParameter.Type = wrappedParameter.Type
            parameterUpdated = true
        end if
        'default
        if overriddenParameter.Default <> wrappedParameter.Default then
            overriddenParameter.Default = wrappedParameter.Default
            parameterUpdated = true
        end if
        'kind
        if overriddenParameter.Kind <> wrappedParameter.Kind then
            overriddenParameter.Kind = wrappedParameter.Kind
            parameterUpdated = true
        end if
        'classifier
        if overriddenParameter.ClassifierID <> wrappedParameter.ClassifierID then
            overriddenParameter.ClassifierID = wrappedParameter.ClassifierID
            parameterUpdated = true
        end if
        'update the parameter if it was changed
        if parameterUpdated then
            overriddenParameter.Update
        end if
    next
end function

答案 2 :(得分:1)

当您告诉EA覆盖或实现基类或接口中的操作时,它会在子类中创建操作的副本。此副本没有引用原始基类/接口,后续更改不会反映在子级中。

如果您将一个实现绘制到一个接口并选择不覆盖任何操作,EA将按照您的预期为它们生成代码,但它不会为抽象类执行此操作 - 即使该子项也是如此是一片叶子。

您始终可以修改代码生成模板(工具 - 源代码生成模板)。他们第一次开始玩弄它们有点棘手,但你很快就会掌握它。