通过继承修改所有实例的MATLAB字段访问?
我正在尝试使用MatlabOOP功能为网格开发数据结构。长话短说,我正在修改一个实例中的字段,该实例继承自与另一个实例相同的基类,并且两个实例都在被修改,就好像该字段被声明为静态的一样 我在MATLAB中的抽象基类(m_元素)中有以下代码:通过继承修改所有实例的MATLAB字段访问?,matlab,oop,inheritance,Matlab,Oop,Inheritance,我正在尝试使用MatlabOOP功能为网格开发数据结构。长话短说,我正在修改一个实例中的字段,该实例继承自与另一个实例相同的基类,并且两个实例都在被修改,就好像该字段被声明为静态的一样 我在MATLAB中的抽象基类(m_元素)中有以下代码: properties(Access = protected) nodes = containers.Map('KeyType','int64', 'ValueType', 'any'); faces = containers.Map('Key
properties(Access = protected)
nodes = containers.Map('KeyType','int64', 'ValueType', 'any');
faces = containers.Map('KeyType','int64', 'ValueType', 'any');
end
这些字段表示每个元素的连接性。例如,哪些节点是第n个节点的邻居,或者哪些面与第n个节点相邻
我还有另外两个类:m_face和m_node,每个类都继承自m_元素。
m_节点非常简单:
classdef m_node < m_element
properties
x = 0;
y = 0;
z = 0;
end
methods
function node = m_node(gmsh_id, x, y, z)
node = node@m_element(gmsh_id);
node.x = x;
node.y = y;
node.z = z;
end
end
end
m_face构造函数希望face ID作为第一个参数出现,其余的应该是构成face的节点。行face.nodes(nod.gmsh_id)=nod代码>似乎是导致我的问题的原因。我有一个m_网格类,它将容纳每个节点和面:
classdef m_mesh < handle
properties(SetAccess = private)
nodes = containers.Map('KeyType','int64', 'ValueType', 'any');
faces = containers.Map('KeyType','int64', 'ValueType', 'any');
end
methods
function theMesh = m_mesh(msh)
for idx = 1:numel(msh.POS(:,1))
n = msh.POS(idx,:);
theMesh.nodes(idx) = m_node(idx, n(1), n(2), n(3));
end
for idx = 1:numel(msh.TRIANGLES(:,1))
ele = msh.TRIANGLES(idx,:);
nod(1) = theMesh.nodes(ele(1));
nod(2) = theMesh.nodes(ele(2));
nod(3) = theMesh.nodes(ele(3));
theMesh.faces(idx) = m_face(idx, nod(1), nod(2), nod(3));
end
end
end
end
i_节点返回实例映射值。那怎么可能呢?如果我还没有设置,为什么我的第一个(以及所有其他!)节点有五个相邻的节点?当我从随机实例访问此字段时,为什么MATLAB要更改所有实例和所有子类的非静态字段?您应该初始化构造函数中的节点
和面
属性,而不是默认属性值
这是怎么回事?首先要注意的是,containers.Map
是一个句柄
类
MATLAB中的正常变量具有值行为:
>> a = 1;
>> b = a;
>> a = 2;
>> b
b =
1
>> a = figure;
>> b = a;
>> get(a, 'Name')
ans =
''
>> get(b, 'Name')
ans =
''
>> set(a, 'Name', 'hello')
>> get(b, 'Name')
ans =
hello
请注意,b
在您更改a
时没有更改-它是a
的副本,a
和b
是具有传递值行为的值变量
其他一些变量具有句柄行为:
>> a = 1;
>> b = a;
>> a = 2;
>> b
b =
1
>> a = figure;
>> b = a;
>> get(a, 'Name')
ans =
''
>> get(b, 'Name')
ans =
''
>> set(a, 'Name', 'hello')
>> get(b, 'Name')
ans =
hello
请注意,当您更改a
时,b
已更改-它是对a
的引用,a
和b
是具有传递引用行为的句柄变量
containers.Map
变量是句柄变量
第二件需要注意的事情是,属性默认值在类第一次实例化时计算一次。(如果您使用清除类
清除类定义,则下次实例化时将再次对其求值)。它们不会在每次创建对象时进行计算
因此,第一次创建对象时,类被实例化,计算containers.Map
,之后的每个对象都将获得与其属性相同的containers.Map
。由于它是一个句柄变量,因此对一个对象中的属性所做的更改将在其他对象的属性中引用
您不希望这样:相反,您应该初始化类构造函数中的值。然后,每次构造对象时,它都会被单独计算,并且每个对象都会得到一个单独的对象
这种行为(即,当您将变量处理为属性默认值时)可能会令人困惑,但我认为这是正确的行为——它是有文档记录的,尽管我认为它可以更清楚地标示出来。这里是讨论这个话题的地方——在评论中,作者、我和一位负责OO语法和设计的MathWorks开发人员讨论了这个问题。Dude!谢谢这让我疯狂。我一定会阅读文章。你知道,我以前习惯于用C++、java和其他OO语言编程。所以这种行为并没有发生在我身上,即使我已经习惯了值/句柄二元性。现在我明白了。