2012-08-08 13 views
9

creazione di una sottoclasse di dynamicprops permette a me di aggiungere le proprietà in modo dinamico a un oggetto:è possibile aggiungere metodi al volo alle classi MATLAB (programmazione orientata agli oggetti)?

addprop(obj, 'new_prop') 

questo è grande, ma mi piacerebbe anche creare set/get funzioni per queste proprietà al volo. O funzioni di analisi che funzionano su queste proprietà dinamiche.

La mia esperienza con Matlab è stata così lunga, che una volta creata un'istanza di una classe, non è possibile aggiungere nuovi metodi. Questo è molto complicato, perché il mio oggetto può contenere molti dati, che dovrò ricaricare ogni volta che voglio aggiungere un nuovo metodo (perché devo fare clear classes).

Quindi c'è un modo per aggiungere metodi al volo?

+0

È possibile aggiungere nuovi metodi finché si eliminano le classi in seguito, ma si desidera aggirare il problema. Non penso che funzionerà in generale. –

risposta

10

Non è possibile aggiungere metodi come aggiungere proprietà dinamiche. Tuttavia, ci sono due modi per implementare nuovi metodi durante lo sviluppo che non richiedono di ricaricare i dati ogni volta.

(1) Scrivo i metodi standard come funzioni separate e li chiamano come myMethod(obj) durante lo sviluppo. Una volta che sono sicuro che sono stabili, aggiungo la loro firma nel file di definizione della classe - questo richiede uno clear classes, ovviamente, ma è molto ritardato, e di tanto in tanto potrebbe essere necessario chiudere Matlab, in ogni caso .

(2) Con i metodi set/get, le cose sono un po 'più complicate. Se si utilizza dynamicprops per aggiungere nuove proprietà, è anche possibile specificare i loro metodi set/get, tuttavia (molto probabilmente, questi metodi/funzioni vorranno ricevere il nome della proprietà in modo che sappiano a cosa fare riferimento):

addprop(obj,'new_prop'); 
prop = findprop(obj,'new_prop'); 
prop.SetMethod = @(obj,val)yourCustomSetMethod(obj,val,'new_prop') 

EDIT

(2,1) Ecco un esempio di come impostare una proprietà nascosta per archiviare e recuperare i risultati (in base a jmlopez' answer). Ovviamente questo può essere migliorato molto se si dispone di una migliore idea che cosa si sta effettivamente progettando

classdef myDynamicClass < dynamicprops 
    properties (Hidden) 
     name %# class name 
     store %# structure that stores the values of the dynamic properties 
    end 
    methods 
     function self = myDynamicClass(clsname, varargin) 
      % self = myDynamicClass(clsname, propname, type) 
      % here type is a handle to a basic datatype. 
      self.name_ = clsname; 
      for i=1:2:length(varargin) 
       key = varargin{i}; 
       addprop(self, key); 
       prop = findprop(self, key); 
       prop.SetMethod = @(obj,val)myDynamicClass.setMethod(obj,val,key); 
       prop.GetMethod = @(obj)myDynamicClass.getMethod(obj,key); 
      end 
     end 
     function out = classname(self) 
      out = self.name_; 
     end 
    end 
    methods (Static, Hidden) %# you may want to put these in a separate fcn instead 
     function setMethod(self,val,key) 
      %# have a generic test, for example, force nonempty double 
      validateattributes(val,{'double'},{'nonempty'}); %# will error if not double or if empty 

      %# store 
      self.store.(key) = val; 

     end 
     function val = getMethod(self,key) 
      %# check whether the property exists already, return NaN otherwise 
      %# could also use this to load from file if the data is not supposed to be loaded on construction 
      if isfield(self.store,key) 
       val = self.store.(key); 
      else 
       val = NaN; 
      end 
     end 
    end 
end 
+0

quindi 'myMethod' sarà in realtà una funzione generica (e non un metodo di classe) che puoi modificare a tuo piacimento, giusto? – memyself

+1

@memyself: esattamente. In seguito, puoi copiare 'myMethod' nel file classdef, o semplicemente aggiungere la firma al file classdef e spostare' myMethod' nella cartella della classe. – Jonas

+0

questo è un bel trucco: non ci avevo mai pensato! – memyself

3

Sto aggiungendo questa risposta perché penso che questo non è intuitivo. Almeno non a me stesso in questo momento. Dopo aver trovato questa domanda ho pensato di avere quello che dovevo essere in grado di definire i metodi set/get per la mia classe dinamica. Tutto quello che volevo ottenere con questo era qualcosa di simile a ciò che Python fa con il suo metodo __setattr__. In ogni caso, ecco un continuation della classe creato da @jonas qualche tempo fa con alcune modifiche per aggiungere il nostro metodo di set personalizzato.

classdef myDynamicClass < dynamicprops 
    properties (Hidden) 
     name_ %# class name 
    end 
    methods 
     function self = myDynamicClass(clsname, varargin) 
      % self = myDynamicClass(clsname, propname, type) 
      % here type is a handle to a basic datatype. 
      self.name_ = clsname; 
      for i=1:2:length(varargin) 
       key = varargin{i}; 
       addprop(self, key); 
       prop = findprop(self, key); 
       prop.SetMethod = makefunc(key, varargin{i+1}); 
      end 
     end 
     function out = classname(self) 
      out = self.name_; 
     end 
    end 
end 

function h = makefunc(key, argtype) 
    h = @newfunc; 
    function newfunc(obj, val) 
     obj.(key) = argtype(val); 
    end 
end 

Con questa classe sto definendo il metodo set in modo che il parametro passato per l'attributo viene copiato il tipo giusto. Per capire cosa intendo considerare quanto segue utilizzo:

>> p_int = myDynamicClass('Point', 'x', @int8, 'y', @int32); 
>> p_int.x = 1000 

p_int = 

    myDynamicClass with properties: 

    y: [] 
    x: 127 

>> class(p_int.x) 

ans = 

int8 

Con questo abbiamo costretto l'attributo x ad essere un numero intero di 8 bit che può contenere solo numeri interi da -128 a 127. Da notare anche come la classe di ogni attributo ci dà il tipo previsto.

+1

Questo è corretto. Si noti che quando si definiscono metodi set/get personalizzati, si può correre il rischio di ricorsioni infinite, poiché il parser Matlab non sempre saprà di evitare di chiamare il metodo set mentre si assegna il valore della proprietà. Per semplificarti la vita (anche a scopo di debug), può essere utile avere una proprietà nascosta per memorizzare i valori, a cui si accede successivamente dai metodi getter/setter. – Jonas

+1

@Jonas ottimo commento - potresti approfondire un po 'la proprietà nascosta e come implementarla? – memyself

+0

@Jonas, così simile alla variabile '__dict__' di python. Citano la possibilità di una ricorsione infinita [qui] (http://docs.python.org/2/reference/datamodel.html#object.__setattr__). C'è qualche documentazione su MATLAB che spiega come farlo? – jmlopez

Problemi correlati