JnBrymn
JnBrymn

Reputation: 25353

Matlab proxy class issue. (re: dependent properties)

Consider the following Matlab (2009a) classes:

classdef BigDeal < handle
    properties
        hugeness = magic(2000);
    end
    methods
        function self = BigDeal()
        end
    end
end


classdef BigProxy < handle
    properties(Dependent)
        hugeness
    end
    properties(Access = private)
        bigDeal
    end
    methods
        function self = BigProxy(bigDeal)
            self.bigDeal = bigDeal;
        end
        function value = get.hugeness(self)
            value = self.bigDeal.hugeness;
        end
    end
end

Now consider the following use of them:

Setup:

>> b = BigDeal

b = 

  BigDeal handle

  Properties:
    hugeness: [10x10 double]

  Methods, Events, Superclasses

OneLayer:

>> pb = BigProxy(b)

pb = 

  BigProxy handle

  Properties:
    hugeness: [10x10 double]

  Methods, Events, Superclasses

TwoLayers:

>> ppb = BigProxy(pb)

ppb = 

  BigProxy handle with no properties.
  Methods, Events, Superclasses

Question: Why is my double layered proxy unable to see the hugeness when the single layer can? Dependent properties can be calculated - but does this go only one layer deep for some reason?


Update: See my answer below for workaround.

Upvotes: 4

Views: 582

Answers (2)

JnBrymn
JnBrymn

Reputation: 25353

Gnovice provided a good answer to the question "why," thus I awarded him the green check of glory. However, for those wanting a work around, you can do something like this:

classdef BigDeal < handle
    properties
        hugeness = magic(10000);
    end
    methods
        function self = BigDeal()
        end
    end
end


classdef BigProxy < handle
    properties(Dependent)
        hugeness
    end
    properties(Access = private)
        bigDeal
    end
    methods
        function self = BigProxy(bigDeal)
            self.bigDeal = bigDeal;
        end
        function value = get.hugeness(self)
            value = self.getHugeness;
        end
    end
    methods(Access = private)
        function value = getHugeness(self)
            if isa(self.bigDeal,'BigProxy')
                value = self.bigDeal.getHugeness;
            else
                value = self.bigDeal.hugeness;
            end
        end
    end
end

which will allow you to do the following

>> b = BigDeal;
>> pb = BigProxy(b);
>> ppb = BigProxy(pb);

And each of {b,pb,ppb} will all have the same public methods and properties. The only drawback is that I have had to (unnecessarily IMHO) clutter up BigProxy with a new private getter.

Upvotes: 4

gnovice
gnovice

Reputation: 125854

The problem here is two-fold:

  1. The BigProxy object constructor is designed to accept an input object that has a (non-dependent) hugeness property (like a BigDeal object), which the BigProxy object can then access to compute the value for its own dependent hugeness property.

  2. You are passing a BigProxy object to the BigProxy constructor when you create ppb, and you apparently can't compute a dependent property from another dependent property. For example, this is the error that is thrown when I try to access ppb.hugeness:

    ??? In class 'BigProxy', the get method for Dependent property 'hugeness'
    attempts to access the stored property value.  Dependent properties don't
    store a value and can't be accessed from their get method.
    

    In other words, the outer BigProxy object tries to compute the value for its dependent hugeness property by accessing the stored value of hugeness for the inner BigProxy object, but there is no stored value since it's a dependent property.

I think the fix for a situation like this would be for the BigProxy constructor to check the type of its input argument to make sure it is a BigDeal object, and throw an error otherwise.

Upvotes: 4

Related Questions