2013-07-10 26 views
5

Si supponga di avere un oggetto X della classe MyClass. MyClass ha un metodo compute e quando chiamo U = compute(X,...), matlab chiama automaticamente il metodo di classe. Tuttavia, quello che voglio veramente è chiamare un'altra funzione chiamata anche compute i cui parametri iniziano con un oggetto MyClass. Come faccio a forzare MATLAB a chiamare questa funzione regolare piuttosto che entrare nel metodo di classe?Come forzare MATLAB a chiamare una funzione regolare piuttosto che un metodo di classe quando sono sovraccarichi?

+1

alcun motivo per cui entrambe le versioni non sono metodi membri? potresti anche rendere la funzione esterna un metodo statico della classe, così viene chiamato in modo diverso: 'MyClass.compute (x)' vs. 'compute (x)' – Amro

risposta

6

Non v'è alcun modo per farlo senza fare alcuni cambiamenti sia a nome o la posizione della funzione. Se si controlla Matlab's function precedence order, i metodi vengono sempre eseguiti prima delle normali funzioni esterne. Le tue uniche opzioni pratiche sono:

  1. Modificare il nome della funzione.
  2. Spostare il corpo della funzione per lo stesso script che chiama la funzione (voce 4 nella lista di cui sopra)
  3. spostare il file .m della funzione in una cartella denominata private nella stessa cartella del file di script (punto 5 all'ordine l'elenco)

UPDATE

anche se non è molto pratico per i piccoli progetti, si può anche voler guardare in packaging your functions. Una buona discussione può essere trovata in this SO post.

+0

Il problema è che anche io cambio il nome della funzione in ' compute2', matlab prova ancora a chiamare il metodo class e finisce con la segnalazione di un errore poiché 'compute2' non è definito in' MyClass' ... – OneZero

+0

in realtà se hai rinominato la funzione regolare come 'compute2' verrà chiamato correttamente (I appena provato in R2013a) – Amro

+0

@OneZero Ricorda che è necessario modificare sia il nome della funzione che il nome del file contenente quella funzione. Quindi, per esempio, finirai con 'function x = compute2 (obj)' nel file 'compute2.m'. – Bee

2

Se il compute capita di essere un incorporato MATLAB, è possibile utilizzare

builtin('compute', ...) 

in caso contrario, non c'è modo - vedere la risposta di Bee.

+0

Buon punto. Ho appena dato per scontato che la sua funzione 'compute' accetta l'oggetto personalizzato come primo parametro, non è una funzione incorporata. – Bee

+1

@Acqua: vero. Con ogni probabilità il PO non ha a che fare con un builtin. Ma qualcun altro potrebbe: p –

2

Se hai un disperato bisogno di questo, allora puoi fare qualcosa come il seguente. Vi suggerisco caldamente di non farlo e di seguire la risposta di Bee. Tuttavia, a volte non si ha scelta ...

L'idea è di avvolgere l'istanza in un'altra classe in modo che la distribuzione delle funzioni di MATLAB non visualizzi il metodo compute. Tuttavia, per la tua funzione compute, l'istanza avvolta deve apparire uguale all'istanza originale. Questo è difficile da ottenere, in alcuni casi, ma spesso il seguente è sufficiente:

classdef Wrapper 

    properties (Access = 'private', Hidden = true) 
     core = []; 
    end 

    methods 

     function this = Wrapper(core) 
      this.core = core; 
     end 

     function varargout = subsref(this, S) 
      if nargout > 0 
       varargout = cell(1, nargout); 
       [varargout{:}] = subsref(this.core, S); 
      else 
       subsref(this.core, S); 
      end 
     end 

    end 

end 

Questa classe avvolge un'istanza di un'altra classe e delega tutto accesso in lettura all'istanza avvolto.

Ad esempio, se si dispone di un file chiamato TestClass.m:

classdef TestClass 

    properties 
     name = ''; 
    end 

    methods 
     function this = TestClass(name) 
      this.name = name; 
     end 

     function compute(this) 
      fprintf('Instance method! My name is "%s".\n', this.name); 
     end 
    end 

end 

E una funzione compute.m:

function compute(x) 
    fprintf('Regular function! My name is "%s".\n', x.name); 
end 

Allora funziona così:

>> t = TestClass('t'); 
>> s = struct('name', 's'); 
>> compute(t) 
Instance method! My name is "t". 
>> compute(s) 
Regular function! My name is "s". 
>> w = Wrapper(t); 
>> compute(w) 
Regular function! My name is "t". 

A seconda di cosa la funzione compute non funziona con la tua istanza ght ha bisogno di aggiungere ulteriori funzioni "speciali" a Wrapper (ad es. subsasgn). Si noti anche che questo si interromperà se compute esegue un metaclasse-magic.

+0

+1. Buon lavoro investigativo! – Bee

+0

che l'ultimo 'doStuff (w)' dovrebbe essere 'compute (w)'. +1 per la soluzione alternativa, ma anch'io sconsiglio di utilizzarlo in codice reale :) – Amro

+0

@Amro: Grazie, corretto. Questo è stato lasciato dal mio codice di prova ed errore. –