如何分离接口和公共实现

How to separate Interface and common implementation

我有以下 class 层次结构:

IMyObject % common interface defining methods and properties (abstract properties are supported by MATLAB)
A < IMyObject
B < IMyObject
...

IMyObject 应充当接口,如果可能,不包含代码。

有许多 class 类(A、B、...)派生自 IMyObject,其中 90% 共享某些方法的代码。

直接的方法是使用抽象 class 而不是接口,并在 IMyObject 中定义所有这些代码(可能将其重命名为 MyObjectRoot、MyObjectMaster、AbstractMyObject 或类似名称)。不共享上述方法代码的 10% 将覆盖它们。

但是,我想要一个显式接口class(将接口与代码分开)。

我使用了支持多重继承的"programming language" (MATLAB)。

现在我可以使用该方法来创建 class MyObject_GenericCode 并且 90% classes 不仅会继承自 IMyObject,还会继承 MyObject_Generic class.

由于这个泛型 class 需要访问数据(来自 IMyObject 的抽象属性),因此它们也需要从中派生。

示例:

MyObject_GenericCode < IMyObject
...
% the 90% classes having some kind of common code:
A < IMyObject & MyObject_GenericCode
B < IMyObject & MyObject_GenericCode
....
% 10% just use the interface and implement everything ob their own
Z < IMyObject

问题是钻石问题 - 但在这种情况下更像是理论上的,因为我认为不会有这种情况。

除此之外 - 还有什么令人沮丧的吗?

最后,我发现在 MATLAB 中我可以避免这种情况,因为通用代码 classes 不需要从 IMyObject 继承,但仍然可以从提供的对象访问属性。

示例:

classdef IMyObject
    properties (Abstract)
        Fc;
    end
    methods (Abstract)
        test(this);
    end
end

classdef MyObject_GenericCode
    methods
        function test(this)
            fprintf(1, 'Value of Fc: %d\n', this.Fc);
        end
    end
end

classdef A < IMyObject & MyObject_GenericCode
    properties
        Fc;
    end

    methods
        function this = A()
            this.Fc = 999;
        end
    end
end

myObj = A();
myObj.test();

哪个returns

Value of Fc: 999

没有错误。尽管这可行,但对我来说听起来有点 "fishy"。

哪种方式合适?

在你的情况下没有必要使用多重继承。 Matlab 的 OOP 没有显式接口 classes,但如果 class 仅包含抽象方法和属性,实际上它就像一个接口。通用 class 可以实现该接口的一部分,留下一些 methods/properties 抽象,由子 class 实现。

因此您的层次结构可能如下所示:

classdef IMyObject
    properties (Abstract)
        Fc;
    end
    methods (Abstract)
        test(this);
    end
end

classdef MyObject_GenericCode < IMyObject
    properties (Abstract)
        Fc;
    end

    methods
        function test(this)
            fprintf(1, 'Value of Fc: %d\n', this.Fc);
        end
    end
end

classdef A < MyObject_GenericCode
    properties
        Fc;
    end

    methods
        function this = A()
            this.Fc = 999;
        end
    end
end