4

我试图找出创建替代 C++ 模板或 Java 通用对象的最佳方法。由于几个不同的原因,我过去曾多次想这样做,但是现在我想做的是为几个相关类创建 saveobj 和 loadobj 函数。我的想法是我想要一组通用的例程来创建一个默认结构,然后再进一步操作它以按照我想要的方式获得结构。

我不能简单地使用外部函数,因为我需要访问对象的所有公共(不是问题)和受保护(问题)非瞬态属性才能创建 loadobj 和 saveobj。

然后我考虑使用抽象接口。然而,使用抽象接口给我带来了同样的问题。相同,复制粘贴在我所有目标文件中的代码。因此,我想到了使用某种与多重继承相结合的成熟对象(我的大多数对象已经从接口的基本具体化继承)。我认为使用超类可以让我公开子类受保护的属性,但它似乎不是那样工作的。有什么建议么?

这是保存 obj 方法的多重继承方法(我目前最接近的方法)的示例。

序列化器.m

% Serializer.m
classdef Serializer 

  methods
    function [saveObj] = saveobj( obj )

      % Get metadata about the Object
      meta = metaclass( obj );
      meta = meta.PropertyList;

      for p = meta'
        if p.Transient | p.Dependent
          continue; % Only serialize the correct fields
        end

        saveobj.(p.Name) = { obj.(p.Name) }; % Serialize
      end % for ( property )
    end % function ( saveobj )
  end % methods
end % classdef ( Serializer )

TestSerializerA.m

% TestSerializerA.m
classdef TestSerializerA < Serializer
  properties
    PropA = 'a';
  end % properties ( public )

  properties( Access = protected )
    HiddenA = 'ha'
  end % properties ( protected )
end % classdef ( TestSerializerA )

TestSerializerB.m

% TestSerializerB.m
classdef TestSerializerB < TestSerializerA & Serializer

  properties
    PropB = 'b'
  end

  properties( Access = protected )
    HiddenB = 'hb';
  end % properties ( protected )

end % classdef ( TestSerializerB )  
4

1 回答 1

0

解决方案

您可以使用访问列表来完成您想要做的事情。您可以允许Serializer类访问您想要序列化的任何受保护/私有类成员。这允许每个类自行确定其哪些成员被序列化。由于您允许访问Serializer,因此您不想继承它。如果这样做,层次结构中的所有类都可以访问这些成员。这是重写的Serializer类:

classdef Serializer

    methods
        function SerializedObj = serialize(~, Obj)
            % Get metadata about the Object
            meta = metaclass(Obj);
            meta = meta.PropertyList;

            for p = meta' %'
                if p.Transient || p.Dependent
                    continue; % Only serialize the correct fields
                end
                try
                    SerializedObj.(p.Name) = { Obj.(p.Name) }; % Serialize
                catch Me
                    % the class has chosen not to allow this property to be
                    % serialized. decide how to handle it.
                    if ~strcmp(Me.identifier, 'MATLAB:class:GetProhibited')
                        Me.rethrow()
                    end
                end
            end
        end 

    end 

end

请注意,您可以决定如何处理访问限制。在上面的例子中,我什么都不做。但是您可以发出警告,抛出错误等......

现在,不是从 继承,而是Serializer创建一个抽象Serializable类,它将启用序列化。

classdef (Abstract) Serializable

    properties (Access = private)
        Serializer_ = Serializer()
    end

    methods        
        function savedObj = saveobj(This)
            savedObj = This.Serializer_.serialize(This);
        end 

    end

end

现在,您希望启用序列化的任何类都将额外继承自Serializable. 您可以指定Serializer有权访问的受保护/私有成员。

例子

下面的类有两个可序列化属性和一个隐藏(不可序列化)属性。

classdef TestSerializerA < Serializable
  properties
    PropA = 'a';
  end

  properties( Access = {?TestSerializerA, ?Serializer} )
      % This property is protected and serializable
      SerializableA = 'sa'
  end 

  properties (Access = private)
      % This property is private and not serializable
      HiddenA = 'ha';
  end
end

这是来自 MATLAB 的结果:

>> Test = TestSerializerA

Test = 

  TestSerializerA with properties:

    PropA: 'a'

>> b = saveobj(Test)

b = 

            PropA: {'a'}
    SerializableA: {'sa'}

下一个示例继承自TestSerializerA,并具有另外两个可序列化属性和一个隐藏属性。

classdef TestSerializerB < TestSerializerA & Serializable

    properties
        PropB = 'b';
    end

    properties (Access = {?TestSerializerB, ?Serializer})
        % This property is protected and serializable.
        SerializableB = 'sb';
    end

    properties (Access = protected)
        % This property is protected and not serializable.
        HiddenPropB = 'hb';
    end

end

请注意这里不需要重新继承Serializable,但可以更容易地阅读代码。

最后,来自 MATLAB 的结果:

>> Test = TestSerializerB

Test = 

  TestSerializerB with properties:

    PropB: 'b'
    PropA: 'a'

>> b = saveobj(Test)

b = 

            PropB: {'b'}
    SerializableB: {'sb'}
            PropA: {'a'}
    SerializableA: {'sa'}

我希望这有帮助!

于 2014-05-29T20:35:01.440 回答