lua - tutorial - que es namespace en c#
Confusión al usar la notación "." Con__index y el espacio de nombres en Lua (1)
Entonces, ¿por qué la tabla de la lista llama __index y luego se asigna a la lista .__ index?
En ninguna parte de su código, la tabla de la lista llama a __index
. Sin embargo, la parte de asignación es un idioma Lua común (también conocido como hack) para guardar algo de memoria. Conceptualmente hay 4 tipos diferentes de tablas involucradas:
- objetos de la lista (las tablas creadas a través de
{length=0}
en su código) - un metatable (que contiene un campo
__index
) que modifica el comportamiento de los objetos de lista cuando intenta acceder a campos que no existen en el objeto - la clase de
list
, que contiene todos los métodos para objetos de lista (como el método depush
), y también sirve como un constructor para objetos de lista una metatabla (que contiene un campo
__call
) para la clase delist
, para que pueda llamar a la tabla delist
como si fuera una función
Como los campos metatabla siempre comienzan con dos guiones bajos ( __
), y los métodos normales generalmente no lo hacen, puede poner campos metatabla y métodos normales uno al lado del otro en una sola tabla sin conflicto. Y esto es lo que pasó aquí. La list
clase de list
también sirve como metatable para objetos de lista. Entonces, usando este truco puede guardar la memoria que normalmente necesitaría para el metatabla separado (el tamaño en bytes para Lua 5.2 en un Linux x86-64 se muestra entre corchetes en las barras de título de la tabla, por cierto):
¿Window.mt simplemente crea una tabla?
No, {}
crea una tabla. Sin embargo, esta nueva tabla se guarda bajo la clave "mt"
en la tabla de la Window
, probablemente para dar a los usuarios de esta Window
"clase" acceso directo a la metatabla que se utiliza para los objetos de la ventana. Dado solo el código que mostró, esto no es estrictamente necesario, y podría haber usado una variable local en su lugar.
¿Por qué necesitamos Window = {} como un espacio de nombres aquí?
En principio, puede almacenar Window.mt
, Window.new
y Window.prototype
separado, pero eso sería engorroso si tiene varias "clases" como Window
. De esta forma puede evitar conflictos de nombres, y usar la "clase" de Window
ve mejor.
Otra razón podría ser que require
solo puede devolver un único valor de una definición de módulo, y si desea exportar múltiples valores (como new
, mt
y prototype
) desde un módulo, necesita una tabla para agruparlos (o usar global variables, pero eso se considera mal estilo).
Estoy confundido de las siguientes dos sintaxis con "."
Por lo que entiendo, se llama
__index
cuando una clave no existe en una tabla pero existe en su metatabla. Entonces, ¿por qué la tabla de la lista llama__index
y luego se asigna a lalist.__index
?list = {} list.__index = list setmetatable(list, { __call = function(_, ...) local t = setmetatable({length = 0}, list) for _, v in ipairs{...} do t:push(v) end return t end }) function list:push(t) if self.last then self.last._next = t t._prev = self.last self.last = t else self.first = t self.last = t end self.length = self.length + 1 end . . . local l = list({ 2 }, {3}, {4}, { 5 })
¿
Window.mt
simplemente crea una tabla? ¿Por qué necesitamosWindow = {}
como un espacio de nombres aquí?Window = {} -- create a namespace Window.mt = {} -- create a metatable Window.prototype = {x=0, y=0, width=100, height=100, } function Window.new (o) setmetatable(o, Window.mt) return o end Window.mt.__index = function (table, key) return Window.prototype[key] end w = Window.new{x=10, y=20} print(w.width) --> 100