包含标量分类的自定义类显示为"[1x1 categorical]",而不是显示类别



在 MATLAB R2014b 上,当您有一个struct(或自定义类)具有标量categorical字段时,当显示struct时,它将显示[1x1 categorical]而不是我想要实现的目标,如下所示。

女工程师:

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

输出:

struct = 
    field: [1x1 categorical]

我想要的输出:

struct = 
    field: category

或:

struct = 
    field: category    [1x1 categorical]

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

我可以在我的类方法中重载disp,但随后我需要从disp本身重写大量显示代码,而不仅仅是更改struct字段中标量categorical显示的方式。

关于如何实现这一目标的任何想法?如果您的答案涉及类定义中的重载disp,那么除了按照我想要的方式显示 categorical 属性之外,我想看看如何像普通disp(obj)一样显示对象的其他属性。您的任何想法或想法可能会帮助我写下自己的答案,所以请分享任何。

在玩了一段时间之后,我想我终于有一些东西可以在自定义类中显示这些标量categorical值。

基本思想是我重载了持有categorical的属性的get方法。然后,我可以检查调用堆栈以查看尝试获取变量值的内容。如果它是我们的重载 disp 方法(每当我们想要显示我们的类时都会调用它),那么如果它只是一个标量categorical,我返回类别名称。否则,我返回属性本身的值(作为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]

注意:这似乎只是 R2014b 和 R2015a 中的问题。它已在所有后续版本中修复。

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

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类是matlab.mixin.Copyable的子类,而又是handle的子类。它为 disfmtTest 类提供 copy 方法,该方法用于临时创建一个副本,其中属性prop的值更改为方法 dispfmt 中的任何所需显示格式。然后,使用 matlab.mixin.Copyable 提供的常规disp函数显示对象的修改副本。

演示

运行obj = dispfmtTest产量

d = 
  dispfmtTest with properties:
    prop: '1'

class(d.prop)产量

ans =
categorical

这是我预期的行为。也可以使用 isscalar 实现对数组属性的支持。

最新更新