包含标量分类的自定义 class 显示为“[1x1 分类]”而不是显示类别

Custom class containing a scalar categorical displays as "[1x1 categorical]" instead of displaying the category

在 MATLAB R2014b 上,如果 struct(或自定义 class)的字段是标量 categorical,当显示 struct 时,它将显示 [1x1 categorical] 而不是我想要达到的效果,如下所示。

MWE:

struct.field = categorical({'category'})

输出:

struct = 
    field: [1x1 categorical]

我想要的输出:

struct = 
    field: category

或:

struct = 
    field: category    [1x1 categorical]

我想要这个,因为我正在写一些 classes 有一个 categorical 属性 总是标量;因为我根据定义知道这一点,所以我不需要将对象的类别显示为 [1x1 categorical]。当显示自定义对象时,我希望它显示类别。

我可以在我的 class 方法中重载 disp,但是我需要从 disp 本身重写很多显示代码,而不仅仅是改变标量的方式categoricalstruct 字段显示。

关于如何实现这个的任何想法?如果您的答案涉及在 class 定义中重载 disp,那么我想看看除了显示 [=16] 之外,您还可以像正常 disp(obj) 一样显示对象的其他属性=] 属性 我想要的方式。你有任何想法或想法可能会帮助我写下我自己的答案,所以请分享任何。

玩了一会儿之后,我想我终于有了一些可以在自定义 class.

中显示这些标量 categorical 值的东西

基本思想是我为持有 categorical 的 属性 重载 get 方法。然后我可以检查调用堆栈以查看 什么 正在尝试获取变量的值。如果它是我们重载的 disp 方法(在我们想要显示我们的 class 时调用),那么我 return 类别名称,如果它只是一个标量 categorical。否则,我 return 的值是 属性 本身(作为 categorical)。

它绝对不是最优雅的,因为它依赖于 dbstack,但它似乎工作得很好。

classdef categoryclass < handle

    properties
        a = categorical({'category'});
    end

    methods
        % Get Method for "a" property
        function res = get.a(self)

            % Get the call stack to determine *what* called this
            stack = dbstack();

            methodname = sprintf('%s.disp', class(self));

            % If it is a scalar and it was called by our overloaded display
            % method, then return the category name
            if isscalar(self.a) && isa(self.a, 'categorical') && ...
                strcmp(methodname, stack(end).name)
                res = categories(self.a);
                res = res{1};
            % Otherwise return just the value itself
            else
                res = self.a;
            end
        end

        % This ensure that disp() shows up in the stack
        function disp(self)
            % Simply call the built-in display function
            builtin('disp', self);
        end
    end
end

现在,如果我们尝试一下。

cls = categoryclass()

  categoryclass with properties:

       a: 'category'

检查当我们请求值时,我们 实际上 得到 categorical

class(cls.a)

    ans =  

       categorical

现在更改它的值。

cls.a = categorical({'another category'})

  categoryclass with properties:

       a: 'another category'

现在使用两个类别

cls.a = categorical({'one', 'two'})

  categoryclass with properties:

       a: [1x2 categorical]

NOTE: This only appears to be an issue in R2014b and R2015a. It was fixed in all later releases.

已经有一段时间了,但今天我又需要这个了。我想到了另一种显示标量 categorical 变量的方法。下面的示例 class 可以解决问题。

classdef dispfmtTest < matlab.mixin.Copyable
    properties
        prop = categorical(1) % default value is a scalar categorical
    end
    methods
        function dispfmt(obj) % dispfmtTest object to display format
            obj.prop = char(obj.prop); % convert to char type
        end
        function disp(self)
            obj = copy(self); % copy is provided by superclass
            dispfmt(obj)
            disp@matlab.mixin.Copyable(obj) % call superclass disp
            delete(obj)
        end
    end
end

dispfmtTest class 是 matlab.mixin.Copyable 的子class,而后者又是 handle 的子class。它为disfmtTestclass提供了copy方法,用于临时创建一个副本,将属性prop的值更改为任意值方法 dispfmt 中的显示格式。然后,使用 matlab.mixin.Copyable.

提供的常规 disp 函数显示对象的修改副本

演示

运行 obj = dispfmtTest 产量

d = 
  dispfmtTest with properties:

    prop: '1'

class(d.prop)产生

ans =
categorical

这是我预期的行为。使用 isscalar.

也可以实现对数组属性的支持