如何按需加载物业?

时间:2018-07-16 15:44:35

标签: matlab oop

我想按需加载属性,但我无法使其正常工作。 我有一个带有临时属性foo的类。因此,保存对象时不存储该属性。当我使用一种调用属性'foo'的方法时,我希望foo的值从一个单独的mat文件中加载并存储到对象中,只要它在工作空间中即可。

我尝试使用get和set方法进行操作,但无法使其正常工作。这可能吗?还是我总是添加一行代码来加载该属性?以下代码不能满足我的要求,但可以指示我的尝试。

此外,使用该属性时,下面的代码将继续加载foo.mat文件。我只想加载foo.mat一次,并将其存储为属性,然后从那里检索数据而不是加载。我的问题的原因是foo属性相当大,即本身具有许多属性的类。我只想在需要时加载它,并且不想将其存储在foobar类本身中。

classdef foobar
    properties(Transient = true)
        foo
    end
    methods
        function value = get.foo(obj)
            if isempty(obj.foo)
                value = load('foo.mat');
                disp('load foo.mat');
            end
        end
        function obj = set.foo(obj,value)
            obj.foo = value;
        end
    end
end

1 个答案:

答案 0 :(得分:1)

您在这里有两个主要问题:

  1. 在您的get.foo方法中,一旦加载值,就永远不会更新对象中foo的值,因此它保持为空。

  2. 即使您尝试通过foo方法更新get.foo,在原始对象中它仍然为空,因为您的foobar类是value class。修改值类对象的方法必须返回修改后的对象作为输出,因为它们实际上是在修改对象的 copy 。值类的set方法返回用于覆盖原始对象的修改后的对象,但是get方法不会返回修改后的对象(因为通常不希望它们被修改)。要克服该限制,您将需要使用handle class的类似引用的行为(这里是a related question,您可能需要查看更多背景知识)。

因此,为了获得所需的行为,您必须将foobar作为handle类的子类来实现,并在首次加载foo字段时进行更新:

classdef foobar < handle    % Inherit from handle class

  properties(Transient = true)
    foo
  end

  methods

    function value = get.foo(obj)
      if isempty(obj.foo)
        value = load('foo.mat');
        disp('load foo.mat');
        obj.foo = value;       % Update foo
      end
      value = obj.foo;         % Return current foo value
    end

    function set.foo(obj, value)  % Return value is unnecessary for handle class
      obj.foo = value;
    end

  end

end

这现在应该可以为您提供所需的行为(即foo仅在首次访问时加载)。

注意任何调用get.foo的方法都会初始化foo。您可能会忽略的一种方法是disp方法,因为它是默认为类创建的。 default display for a class object将显示类名称,后跟一系列非隐藏的公共属性及其值。请注意,当我从上方创建带有和不带有分号的类foobar的对象时会发生什么:

>> f = foobar;  % Display is suppressed
>> f = foobar

f = 

load foo.mat               % foo gets initialized...
  foobar with properties:

    foo: [1×1 struct]      % ...because its value is displayed here

如果要避免这种情况,可以overload the disp function用于foobar对象,以使显示该对象不会访问(并因此初始化)foo。例如,您可以将此方法添加到上面的foobar类中:

    function disp(obj)
      disp('     foobar object');
    end

现在,在显示对象时您不会初始化foo

>> f = foobar

f = 

     foobar object  % foo not yet initialized
>> a = f.foo;
load foo.mat        % foo initialized because we accessed it