我想按需加载属性,但我无法使其正常工作。
我有一个带有临时属性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
答案 0 :(得分:1)
您在这里有两个主要问题:
在您的get.foo
方法中,一旦加载值,就永远不会更新对象中foo
的值,因此它保持为空。
即使您尝试通过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