Metatablas y Métodos Meta
Las metatablas permiten sobrecargar operadores y modificar el comportamiento de funciones integradas. Una tabla puede asignar otra como metatabla, definiendo métodos meta que alteran operaciones básicas, similar a los métodos mágicos de Python.
Ejemplo Básico: _tostring
import console;
io.open()
var datos = {
valorA = 100;
valorB = 200;
@{
_tostring = function() {
return table.tostring(owner);
}
}
}
io.print("Sin metatabla:", {});
io.print("Con metatabla:", datos);
console.pause(true);
Sobrecarga de Operadores
io.open()
punto1 = { x=5, y=10 }
punto2 = { x=15, y=20 }
punto1@ = {
_add = function(otro) {
return owner.x + otro.x
}
}
resultado = punto1 + punto2
io.print(resultado) // Muestra 20
Implementación con Sunny DLL
Al encapsular funciones DLL de Sunny, los métodos meta simplifican el manejo de memoria y conversión de datos:
namespace sunny;
class Mensaje {
ctor(id) {
this.id = id;
}
@_meta;
}
namespace Mensaje {
Liberar = ::SunnyDLL.api("Free", "void(pointer)");
ObtenerCuerpo = ::SunnyDLL.api("GetRequestBody", "pointer(int)");
envoltorio = function(nombre, id) {
return function(...) {
var ptr = self[nombre](id, ...);
if (type(ptr) == type.pointer) {
var contenido = raw.tostring(ptr);
Liberar(ptr);
return contenido;
}
return ptr;
}
}
_meta = {
_get = function(k) {
return envoltorio(k, owner.id)
}
}
}
// Uso
mensaje = Mensaje(12345);
cuerpo = mensaje.ObtenerCuerpo(); // Conversión y liberación automáticas
Proxy para Monitorización
function proxyParaTabla(original) {
var _meta = {
_get = function(k) {
io.print(`Acceso a ${k}`);
return original[k];
},
_set = function(k, v) {
io.print(`Modificación de ${k} a ${v}`);
original[k] = v;
}
}
return {@_meta};
}
tab = { coordenadaX=10 };
proxy = proxyParaTabla(tab);
proxy.coordenadaX = 30; // Registra la modificación
Métodos Meta Disponibles
| Método | Función | Equivalente Python |
|---|---|---|
| _get | Acceso a propiedades | __getattr__ |
| _set | Asignación de propiedades | __setattr__ |
| _tostring | Conversión a cadana | __str__ |
| _add | Operador + | __add__ |
| _call | Invocación como función | __call__ |
Metatablas para Propiedades
import util.metaProperty;
class Etiqueta {
establecerTexto = function(v) { /* Lógica UI */ }
obtenerTexto = function() { /* Lógica UI */ }
@_metaProp;
}
namespace Etiqueta {
_metaProp = util.metaProperty(
texto = {
_get = function() { return owner.obtenerTexto() },
_set = function(v) { owner.establecerTexto(v) }
}
);
}