【问题标题】:MATLAB: Set inherited properties to read-onlyMATLAB:将继承的属性设置为只读
【发布时间】:2015-07-17 20:17:08
【问题描述】:

假设我有一个称为矩形的超类:

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 的继承属性设置为只读?我希望任何独立(非地图)矩形对象的属性保持可变。

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

【问题讨论】:

  • 你会如何在其他 oop 语言中做类似的事情?您会使用更严格的限定符(例如private 而不是public/protected)覆盖超类属性吗?关于 MATLAB - 一个常见的(虽然不是很 oop;我不喜欢)方法是打破继承关系,并使 Map 成为一个自己的类,该类具有指向某个 Rectangle 的属性和从handle 扩展Rectangle.. 还有一个问题-假设您继承了Map 中的属性,它们是否会被修复,或者如果强制转换为超类可能会改变?
  • 我不知道,MATLAB 是我第一次接触 OOP,除了对 python 的非常简短的介绍,从未涉足继承。我知道 MATLAB 不是一种理想的 OOP 语言,但它是我们在工作中需要使用的。老实说,我只是假设您可以对继承的属性设置约束,但也许不是这样。感谢您提供有关打破继承的提示。

标签: matlab oop inheritance superclass


【解决方案1】:

这似乎是您应该更喜欢组合而不是继承的情况。

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

我建议不要将Map 继承自Rectangle,而应将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

【讨论】:

  • 谢谢。该解决方案有效,您的解释提高了我对 OOP 的理解。我所做的唯一更改是将 rectangleDelegate 的 GetAccess 公开,因为我想访问 Rectangle 中包含的一些方法(为简洁起见,我将这些方法排除在原始示例之外)。例如,如果我想要地图的区域,那么我可以做 Map.rectangleDelegate.area,其中 area 是 Rectangle 类的方法。我想我也可以为 Map 编写小的一行函数,它在 Rectangle 中调用相同的函数。
  • @EddyTheB 当然这是您的选择,但我建议您不要这样做。委托模式的全部意义在于您不公开委托,而是在内部向它委托功能。外部类的用户不应该知道它的存在。我建议将额外的属性添加到Map,然后编写一行get 调用Rectangle 并传递结果的函数。
  • 很公平,我会不做的。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 2019-03-09
  • 1970-01-01
相关资源
最近更新 更多