【问题标题】:Custom class containing a scalar categorical displays as "[1x1 categorical]" instead of displaying the category包含标量分类的自定义类显示为“[1x1 分类]”而不是显示分类
【发布时间】:2016-06-24 01:01:26
【问题描述】:

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

MWE:

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) 一样。你有任何想法或想法可能会帮助我写下我自己的答案,所以请分享。

【问题讨论】:

  • 即使您在类中覆盖disp,此行为也不会改变。您需要为结构本身编写一个自定义的disp 方法,该方法将检查标量并适当地显示它。
  • @Suever - 没错,我想这是相当多的工作。我想知道是否存在我没​​有想到的另一种方式。我的第一个想法是通过首先显示类别来实际重写disp,然后使用普通的disp 函数来显示除类别字段之外的所有内容。如何调用非重载的disp 函数?如果我在类方法中的重定义中使用disp,我会递归调用该类方法。

标签: matlab class oop struct categories


【解决方案1】:

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

基本思想是我为持有categorical 的属性重载get 方法。然后我可以检查调用堆栈以查看 what 正在尝试获取变量的值。如果它是我们重载的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 中的问题。它已在所有后续版本中修复。

【讨论】:

  • 很高兴您在某个地方(在哪里?)找到了这只适用于这两个版本。我今晚或明天将进一步调查。看看mathworks.com/help/matlab/matlab_oop/…mathworks.com/help/matlab/matlab_oop/type-sect1-title-here.html(注意有趣的.html 页面名称,有人显然忘了编辑)。请注意,不使用分号; 会调用display 函数,而后者又会调用disp 函数,因此重载displaydisp 可能会奏效。
  • @Erik 通过实验发现。我正在更详细地研究这个。很快就会发布!
  • @Erik 我已经用一个类定义更新了它,应该像你描述的那样工作。
【解决方案2】:

已经有一段时间了,但今天我又需要这个了。我想到了另一种显示标量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 又是handle 的子类。它为disfmtTest 类提供了copy 方法,该方法用于临时创建一个副本,该副本的属性prop 的值在方法dispfmt 中更改为任何所需的显示格式。然后,使用matlab.mixin.Copyable 提供的常规disp 函数显示对象的修改副本。

演示

运行obj = dispfmtTest 产生

d = 
  dispfmtTest with properties:

    prop: '1'

class(d.prop) 产生

ans =
categorical

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

【讨论】:

    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多