【问题标题】:Can a constructor access the name of the variable its object is being store to?构造函数可以访问其对象存储到的变量的名称吗?
【发布时间】:2011-09-15 21:26:22
【问题描述】:

我希望以下代码将 myClass 实例的 'name' 字段设置为 'super_awesome_name':

super_awesome_name = myClass();

其中myClass的构造函数如下:

function obj = myClass()
    obj.name = ???;
end

在 Matlab 中有没有办法做到这一点?现在我可以用assignin完成一些非常相似的事情,但它使语法非常不自然:

 myClass(super_awesome_name);

其中myClass的构造函数如下:

function obj = myClass(var_name)
    obj.name = assignin('caller',var_name, obj);
end

【问题讨论】:

  • 没有语言功能。 (除了用dbstackdbtype 破解它,但那会很奇怪。)你为什么要这样做?

标签: oop matlab constructor


【解决方案1】:

据我所知,没有方便的方法。您可以自己看到这一点,因为 MATLAB 在构造这样的对象时必须执行一些操作。

  1. 首先构造对象
  2. 将该对象存储在super_awesome_name

但是第 1 步需要来自第 2 步的信息(即变量的名称)。所以你将不得不解决这个问题。

您的解决方案可能有效,但它留下了很大的错误空间。只需考虑super_awesome_name在构造之前未定义的情况:这将由于未初始化的变量而引发异常。

恕我直言,创建一个接受包含名称的字符串(或者可能是变量,因为您可以使用inputname 获取参数的变量名称)的构造函数更容易。但是,使用inputname 比使用assignin 更清晰一些。

为什么需要这样的功能?我正在考虑一种情况,您可能会这样做:

x = myObjectThatHasAName(); % x.name contains 'x'
y = myObjectThatHasAName(); % y.name contains 'y'
x = y;                      % x.name contains 'y' !

所以这可能是您正在寻找的行为,但如果您传递大量变量,它可能会变得非常混乱。在我看来,您正在将调试信息混合到您的实际计算中。

如果您需要在另一个方法或函数中确定实际变量名称的功能,只需使用inputname。然后,您将不需要自己跟踪变量名称,这会带来所有令人困惑的后果。这将是我建议在大多数情况下做的事情。您可以在 MATLAB 文档中查看示例。

另一方面,我认为将变量名存储在对象中的最清晰方法可能是:

classdef myObjectThatHasAName
   properties
      name = '';
   end
   methods
      function obj = myObjectThatHasAName()
      end
      function obj = storeName(obj,name)
         if nargin < 2
            name = inputname(1);
         end
         if ~isempty(name) % && isempty(obj.name)
            obj.name = inputname(1);
         end
      end
   end
end

我还没有对此进行测试(我当前的计算机上缺少 MATLAB),但是下面的代码应该可以做到:

x = myObjectThatHasAName();
x = x.storeName(); 
% or x = storeName(x);
% or x = storeName(x,'x');

如果您不介意开销,您总是可以将storeName 合并到其他方法中(忘记在方法之外调用storeMethod)。这将跟踪对象在最后一次赋值之前所在的变量名。一种可能的方法可能如下所示:

function obj = otherMethod(obj,arguments)
   obj = obj.storeName(inputname(1));
   % actual code for the method
end

这样,当您第一次调用对象上的任何方法时,名称就会被设置(这几乎可以满足您的需求,但我想它会在大多数情况下满足您的需求)。您当然可以调整代码以仅记住第一个分配(只需将 storeName 中的代码注释掉即可)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-25
    • 2018-11-04
    • 2011-12-08
    • 2018-12-26
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    相关资源
    最近更新 更多