MATLAB:将继承的属性设置为只读

时间:2015-05-07 10:10:48

标签: matlab oop inheritance superclass

假设我有一个叫做矩形的超类:

classdef Rectangle
    properties
        width
        height
        x0 = 0
        y0 = 0
        angle = 0
    end
    methods
        function obj = Rectangle(x0, y0, width, height, angle)
            obj.x0 = x0;
            obj.y0 = y0;
            obj.width = width;
            obj.height = height;
            obj.angle = angle;
        end
    end
end

我有一个名为Map的子类,我希望所有属性在设置后都是只读的:

classdef Map < Rectangle
    properties (SetAccess=private)
        filename
    end
    methods
        function obj = Map(filename)
            % Get info from map using a function that uses geotiffread
            [x0, y0, width, height] = GetInfoFromMap(filename);
            obj = obj@Rectangle(x0, y0, width, height, 0);
            obj.filename = filename;
        end
    end
end

如何在Map中将Rectangle的继承属性设为只读?我希望任何独立(非Map)Rectangle对象的属性保持可变。

而且,我如何确保其中一些属性只能采用某些值?即为了我的目的,一个矩形可以有任何角度,但我希望一个地图总是有一个0的角度。但如果我尝试为Map创建一个set.angle方法,以确保角度只能是0,我得到一个错误告诉我“无法在类'BackgroundMap'中为属性'angle'指定一个set函数,因为该属性不是由该类定义的。”

1 个答案:

答案 0 :(得分:2)

这似乎是一种情况,你应该更喜欢组合而不是继承。

在其中一条评论(@ Dev-iL)中提到了这个想法,其中它被描述为“不是非常OOP”。我不同意 - 虽然在许多情况下继承是正确的设计,但组合通常更可取。 (有关此问题的一些讨论,请参阅herehere)。人们可能更喜欢组合的一个典型原因是继承将子类暴露给超类的细节,换句话说它破坏了封装 - 这就是RectangleMap的实现中发生的事情。

我建议代替MapRectangle继承,它应该有Rectangle作为私有(可能是隐藏的)属性。所以你应该把地图看成不是一种矩形,而是要有一个相关的矩形,它委托它的一些功能。

完成后,您可以为Map提供一些属性widthheight等,并将其设为GetAccess=public, SetAccess=private, Dependent。然后在Map中,为每个方法添加get方法,只获取基础Rectangle的属性并将其传递通过。请注意,Map不需要角度属性,因为它始终为零。

classdef Map < handle
    properties (SetAccess=private)
        filename
    end
    properties (Hidden, GetAccess = private, SetAccess-private)
        rectangleDelegate
    end
    properties (Dependent, GetAccess = public, SetAccess = private)
        width
        height
        x0
        y0
    end
    methods
        function obj = Map(filename)
            % Get info from map using a function that uses geotiffread
            [x0, y0, width, height] = GetInfoFromMap(filename);
            obj.rectangleDelegate = Rectangle(x0, y0, width, height, 0);
            obj.filename = filename;
        end
    end
    methods
        function val = get.width(obj)
            val = obj.rectangleDelegate.width;
        end
        % other gets
    end
end