2010-05-03 5 views
5
codice

Esempio:programmazione in lua, oggetti

function Account:new (o) 
    o = o or {} -- create object if user does not provide one 
    setmetatable(o, self) 
    self.__index = self 
    return o 
end 

Tratto da:

http://www.lua.org/pil/16.1.html

Qual è lo scopo della:

self.__index = self 

linea? E perché viene eseguito ogni volta che viene creato un oggetto?

risposta

5

Come altri hanno già detto, self (tabella Account) viene utilizzato come metatabella assegnati agli oggetti creati utilizzando new. Semplificando leggermente (maggiori informazioni disponibili ai link forniti) quando un campo non viene trovato in "o", va alla tabella "Account" perché la metrica di o dice di andare su Account (questo è ciò che fa __index).

Tuttavia, non è necessario eseguirlo ogni volta che viene creato un oggetto. Si potrebbe facilmente attaccare da qualche parte:

Account.__index = Account 

e funzionerebbe pure.

La storia un po 'più a lungo è che se un oggetto o ha una metatabella, e che metatabella ha il set __index campo, poi un fallito campo di ricerca sulla o utilizzerà __index per trovare il campo (__index può essere un tavolo o funzione). Se o ha impostato il campo, non si accede alla funzione __index del metappetibile per ottenere le informazioni. Ancora una volta, però, ti incoraggio a leggere di più sui link forniti sopra.

0

Sono utilizzati per reindirizzare gli accessi alla tabella (y = table [chiave] locale, utilizzati anche nelle chiamate di metodo. Nella riga precedente, l'oggetto o avrà qualsiasi tentativo di accedere alle chiavi reindirizzate al sé dell'oggetto corrente, ereditando senza sforzo tutte le funzioni membro. E possibilmente anche variabili di dati, a seconda di che cosa sia esattamente __index e come funzioni.

3

Lua non è un linguaggio orientato agli oggetti, ma ha tutte le funzionalità per scrivere codice orientato agli oggetti. Tuttavia, è fatto in un modo a la JavaScript. Invece di creare classi in modo esplicito, viene creato un oggetto prototipo e quindi clonato per creare nuove istanze.

Il metametodo __index viene invocato per eseguire ricerche di chiavi sugli accessi in lettura a una tabella quando la chiave non è già presente nella tabella. Pertanto, self.__index = self consente essenzialmente l'ereditarietà di tutti i metodi e campi della classe "Account" dalla nuova "istanza" creata nelle linee o = o or {} e setmetatable(o, self).

Vedi anche:

+0

Ho trovato questo "tutorial" su Lua [ereditarietà] (http: // lua-users.org/wiki/InheritanceTutorial) particolarmente illuminante in combinazione con questa risposta. – Indolering

+0

@Indolering Grazie. Ho inserito il tuo link nella risposta. –

4

La documentazione Lua è un po 'vago su questo dettaglio e molte delle risposte qui sia eco la documentazione Lua e non vi fa bene spiegare questo bocconcino confusione.

La riga self._index = self è presente esclusivamente a beneficio dell'oggetto appena creato, o; non ha alcun impatto significativo o funzionale su Account.

Il campo _index ha solo un significato particolare nel contesto della metatables; pertanto, self._index è solo un normale campo normale per Account. Tuttavia, quando Account viene utilizzato come metatabella per o, il campo _index "diventa" un metamethod per o. (Così che cosa è un campo per Account è un metamethod per o.)

Quando si prendono le due dichiarazioni in combinazione ...

 
(1) setmetatable(o, self) 
(2) self._index = self 

... stai usando Account come metatabella per o su linea (1) e impostazione della metamethod _index per o a Account in linea (2). (Nella riga (2), si imposta anche il "campo vecchio semplice" __index in Account a Account.) Quindi l'aspetto utile di self._index = self non è l'impostazione del campo _index per Account, ma piuttosto l'impostazione di _index metamethod per o.

Quello che segue è funzionalmente equivalente:

 
    setmetatable(o, self) 
    getmetatable(o)._index = self 
+0

Ricorda che mentre __index è un metametodo nel nome, lua fornisce una comoda scorciatoia in cui __index può essere assegnato a una tabella anziché a una funzione. In questi casi, quando viene chiamato __index, viene eseguita una ricerca. Pertanto, quando dici __index = self quello che stai dicendo è, se non riesci a trovare un campo specifico nell'istanza di Account, guarda (aka "index") nella classe Account/prototype stesso. – Aaron

0

Creazione di oggetti (che sono semplicemente tabelle) è molto diversa con Lua. L'idea di base è creare una tabella regolare contenente attributi (funzioni e valori) comuni a tutte le istanze. Questa tabella, chiamerò CAT per Common Attributes Table.

Se si fa riferimento a un attributo in una tabella e Lua non riesce a trovare questo attributo, c'è un modo per dire Lua dove altro cercare l'attributo. Vogliamo che Lua guardi nel CAT per attributi comuni. Metatables risponde a questa necessità. Maggiori informazioni su come funziona dopo.

Abbiamo bisogno anche metodi nella CAT per poter utilizzare valori delle istanze. Self risposte che servono. Quando si chiama una funzione di tabella (metodo) in questo modo: tableName:methodName(), Lua inserisce automaticamente un riferimento all'oggetto tabella come primo parametro. Il nome di questo parametro è self. Anche se il metodo si trova nel CAT, self si riferirà alla particolare tabella di istanza dell'oggetto chiamante.

supponga di avere un gatto di nome auto.

metaCar = { __index = Car } 
-- this table will be used as the metatable for all instances of Car 
-- Lua will look in Car for attributes it can't find in the instance 

Ad esempio:

-- instance table is called mustang  
-- setmetatable(mustang, metaCar) 

Ecco una funzione di uso generale che crea nuovi oggetti istanza e imposta il metatabella per esso. Se il CAT ha una funzione di costruzione (init), viene eseguito anche.

function newObj(metatable) 
..obj = {}  -- create new empty instance object 
..setmetatable(obj, metatable) –- connect the metatable to it 
..if obj.init then -- if the CAT has an init method, execute it 
....obj:init() 
..end 
..return obj 
end