2013-08-12 6 views
5

Sto raggruppando un insieme di funzioni anonime in una struttura e alcune variabili all'interno di quella struttura. C'è un modo per riferirsi a 'sé', cioè la propria struttura? Quello che mi piacerebbe realizzare è che una funzione restituisca alcuni valori in base alle variabili membro. Per semplicità, dire che ho un structun, doveEsiste un "sé" per riferirsi alla propria struttura in MATLAB?

a.value_1 = 3; 
a.value_2 = 2; 
a.sum = @()(self.value_1 + self.value_2) 

C'è qualcosa di simile possibile in MATLAB?

+5

non si dovrebbe piuttosto utilizzare una classe di struct per questo? – Dan

+1

Grazie per le risposte e i commenti rapidi. Ora, mi rendo conto che esiste un modo per definire una classe in MATLAB. – radarhead

risposta

9

Prima objected-oriented programming è stato introdotto in MATLAB (compreso sia classdef-style e le classi di stile obsolete @-directory), uno could creare oggetti leggeri con chiusure e funzioni annidate (mancano eredità ovviamente). Questo concetto esiste anche in altre lingue.

Ecco un esempio:

function s = mystruct() 
    s = struct('value_1',[], 'value_2',2, 'sum',@mysum); 
    s.value_1 = 3; 

    function out = mysum() 
     out = s.value_1 + s.value_2; 
    end 
end 

che viene utilizzato come:

>> s = mystruct() 
s = 
    value_1: 3 
    value_2: 2 
     sum: @mystruct/mysum 
>> s.value_1 = 10;  % NOTE: this wont do what you expect! 
>> s.sum() 
ans = 
    5 

nota che le variabili sono immediatamente catturati durante la creazione di una chiusura (funzioni hanno la loro copia privata se si vuole). Quindi, se si modifica uno dei campi esposti dalla struttura restituita, non si rifletterà nello stato chiuso (pensateli come proprietà di sola lettura).

Una soluzione è quella di fornire metodi di accesso:

function obj = mystruct() 
    % think of those as private properties 
    value_1 = 3; 
    value_2 = 2; 

    % returned object (this or self) 
    obj = struct(); 

    % public accessors for properties 
    obj.value_1 = @accessValue1; 
    function out = accessValue1(in) 
     if nargin > 0, value_1 = in; end 
     out = value_1; 
    end 
    obj.value_2 = @accessValue2; 
    function out = accessValue2(in) 
     if nargin > 0, value_2 = in; end 
     out = value_2; 
    end 

    % member method 
    obj.sum = @mysum; 
    function out = mysum() 
     out = value_1 + value_2; 
    end 
end 

Così ora potremmo dire:

>> s = mystruct() 
s = 
    value_1: @mystruct/accessValue1 
    value_2: @mystruct/accessValue1 
     sum: @mystruct/mysum 
>> x = s.value_1(); % get 
>> s.value_1(10);  % set 
>> s.sum() 
ans = 
    12 

che sta cominciando a guardare come l'approccio consigliato corrente per creare classi:

classdef mystruct < handle 
    properties 
     value_1 = 3; 
     value_2 = 2; 
    end 
    methods 
     function out = sum(obj) 
      out = obj.value_1 + obj.value_2; 
     end 
    end 
end 

Utilizzato in modo simile:

>> s = mystruct() 
s = 
    mystruct with properties: 

    value_1: 3 
    value_2: 2 
>> s.value_1 = 10; 
>> s.sum 
ans = 
    12 

Potremmo anche definire get/set access methods come prima ..

+0

Grazie per la spiegazione dettagliata. – radarhead

2

Questo sembra funzionare, ma penso che si dovrebbe piuttosto creare un class di un struct per fare questo:

a.value_1 = 3; 
a.value_2 = 2; 

a.sum = @(x)(x.value_1 + x.value_2) 

a.sum(a) 
+1

stava per aggiungere la stessa risposta esatta! –

+0

Questo funziona solo per un caso d'uso molto specifico: sarà [totalmente viziato] (http://stackoverflow.com/a/18189781/2278029) in altri se non si capisce cosa sta facendo. – horchler

+0

@horchler In quali casi rovinerà? Questo funziona e ho suggerito di usare piuttosto una classe, quindi non capisco veramente il downovte? – Dan

0

Con questa modifica

a.value_1 = 3; 
a.value_2 = 2; 
a.sum = @()(a.value_1 + a.value_2) 

Poi a.sum() rendimenti 5. Ma cosa succede quando modifichi uno dei valori, in seguito, ad es., Imposta a.value_1 = 5? Ora a.sum() restituisce ... sempre 5. I parametri passati alla funzione anonima vengono valutati al momento dell'istanziazione. Se si desidera che il secondo comportamento funzioni correttamente, è necessario utilizzare uno class. Vedi my answer to this question per ulteriori informazioni. L'unica ragione per utilizzare una funzione come quella che hai è evitare di valutare e archiviare un grande output di una funzione finché non è necessario.

+0

Grazie per la risposta. Una classe è ciò che stavo cercando ma non mi ero reso conto che era disponibile in MATLAB. – radarhead