0Pricing
Lua Academy · Lezione

Metodi delle istanze e self

Definisca metodi usando la sintassi con i due punti e il parametro implicito self.

Metodi delle istanze e self è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Lua Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Lua Academy include 4 lezioni in totale.

self è l'istanza

Quando chiama obj:method(), Lua passa automaticamente obj come primo argomento. Per convenzione, questo parametro si chiama self. Tramite self, il metodo accede ai dati dell'istanza e chiama altri metodi.

local Counter = {}
Counter.__index = Counter

function Counter.new(start)
  return setmetatable({value=start or 0, step=1}, Counter)
end

function Counter:increment()
  self.value = self.value + self.step
end

function Counter:getValue() return self.value end

local c = Counter.new(10)
c:increment(); c:increment()
print(c:getValue())  -- 12

Concatenamento dei metodi

Restituisca self dai metodi per consentire il concatenamento: obj:method1():method2():method3(). Ogni chiamata restituisce lo stesso oggetto, consentendo uno stile fluente. Questo funziona al meglio per i metodi che modificano lo stato.

local Builder = {}
Builder.__index = Builder

function Builder.new()
  return setmetatable({parts={}},Builder)
end

function Builder:add(s) self.parts[#self.parts+1]=s; return self end
function Builder:addAll(t)
  for _,v in ipairs(t) do self.parts[#self.parts+1]=v end
  return self
end
function Builder:build() return table.concat(self.parts," ") end

local result = Builder.new()
  :add("Hello")
  :add("from")
  :addAll({"Lua","OOP"})
  :build()
print(result)  -- Hello from Lua OOP

Chiamare altri metodi

I metodi possono chiamare altri metodi sulla stessa istanza tramite self:otherMethod(). Questo favorisce il riutilizzo del codice all'interno di una classe. Gli helper privati possono essere semplici funzioni local che ricevono esplicitamente self.

local Stack = {}
Stack.__index = Stack

function Stack.new() return setmetatable({_data={},_size=0},Stack) end
function Stack:push(v) self._size=self._size+1; self._data[self._size]=v end
function Stack:pop()
  if self:isEmpty() then return nil end
  local v=self._data[self._size]; self._data[self._size]=nil
  self._size=self._size-1; return v
end
function Stack:peek()
  return not self:isEmpty() and self._data[self._size] or nil
end
function Stack:isEmpty() return self._size==0 end
function Stack:size() return self._size end

local s=Stack.new(); s:push(1);s:push(2);s:push(3)
print(s:pop(),s:peek(),s:size())  -- 3  2  2

Avvertenza sulla sovrascrittura dei metodi

Impostare un campo dell'istanza con lo stesso nome di un metodo della classe nasconde il metodo per quell'istanza. Di solito è un bug: presti attenzione quando i nomi dei campi dell'istanza possono entrare in conflitto con quelli dei metodi.

local Dog = {}
Dog.__index = Dog
function Dog.new(n) return setmetatable({name=n},Dog) end
function Dog:speak() print(self.name..": Woof!") end

local d = Dog.new("Rex")
d:speak()        -- Rex: Woof!

-- Accidental shadow:
d.speak = "loud"  -- now d.speak is a string, not a function
local ok,err = pcall(function() d:speak() end)
print(ok, err)   -- false  attempt to call a string value

Self nelle callback

Passare un metodo come callback fa perdere il self implicito. Racchiuda il metodo in una closure per catturare self.

local Timer = {}
Timer.__index = Timer
function Timer.new(n) return setmetatable({count=n},Timer) end
function Timer:tick()
  self.count=self.count-1
  print("Ticking, count:", self.count)
end

local t = Timer.new(3)

-- Wrong: loses self
-- local cb = t.tick  -- cb(t) works but cb() doesn't

-- Correct: closure captures self
local cb = function() t:tick() end
cb(); cb(); cb()  -- Ticking 3 times

Metodi statici e di istanza

Un metodo statico viene chiamato sulla classe, non su un'istanza. Non ha self (oppure riceve la classe come self). In Lua non esiste una distinzione formale: per convenzione, utilizzi . (non :) per i metodi statici.

local MathUtils = {}
MathUtils.__index = MathUtils

-- Static method (no instance needed)
function MathUtils.clamp(v, lo, hi)
  return math.max(lo, math.min(hi, v))
end

-- Instance method (needs self)
function MathUtils:scale(factor)
  self.value = self.value * factor
end

print(MathUtils.clamp(15, 0, 10))  -- 10
local m = setmetatable({value=5},MathUtils)
m:scale(3)
print(m.value)  -- 15

Metodi mixin

Aggiunga i metodi di una tabella mixin a una classe senza un'ereditarietà formale. Questa è una composizione piatta: copi o referenzi le funzioni del mixin nella tabella della classe.

local Serializable = {}
function Serializable:serialize()
  local parts={}
  for k,v in pairs(self) do
    if type(v)~="function" then
      parts[#parts+1]=k.."="..tostring(v)
    end
  end
  return "{"..table.concat(parts,",").."}"
end

local User = {}
User.__index = User
User.serialize = Serializable.serialize   -- mixin!

function User.new(n,a) return setmetatable({name=n,age=a},User) end

local u = User.new("Alice",30)
print(u:serialize())

Metodi astratti

Lua non impone i metodi astratti, ma può definire un metodo della classe base che genera un errore, obbligando le sottoclassi a sovrascriverlo. È una convenzione per indicare che il metodo "deve essere sovrascritto".

local Shape = {}
Shape.__index = Shape

function Shape.new() return setmetatable({},Shape) end

function Shape:area()
  error(type(self).." must implement area()",2)
end

function Shape:describe()
  print("Shape area:", self:area())
end

local sq={}
setmetatable(sq,{__index=Shape})
function sq:area() return 4*4 end

sq:describe()  -- Shape area: 16

Tabelle dei metodi

Per le classi con molti metodi, li organizzi in gruppi in base alla funzionalità. Tutti i metodi nella stessa tabella condividono la stessa ricerca nella metatabella, ma può suddividerli per responsabilità utilizzando sottospazi dei nomi.

local Entity = {}
Entity.__index = Entity

Entity.Physics = {}
function Entity.Physics:applyForce(fx,fy)
  self.vx=(self.vx or 0)+fx
  self.vy=(self.vy or 0)+fy
end

Entity.Render = {}
function Entity.Render:draw()
  print(string.format("Draw at (%g,%g)",self.x or 0,self.y or 0))
end

-- Mix into main class
for k,v in pairs(Entity.Physics) do Entity[k]=v end
for k,v in pairs(Entity.Render) do Entity[k]=v end

function Entity.new(x,y) return setmetatable({x=x,y=y},Entity) end
local e=Entity.new(10,20); e:draw(); e:applyForce(5,0); print(e.vx)

Delegazione ed ereditarietà

Preferisca la delegazione (mantenere un riferimento) a catene di ereditarietà profonde. Una classe può delegare a un altro oggetto invece di ereditarne, mantenendo basso l'accoppiamento e concentrando ogni classe sul proprio compito.

local Logger = {}
Logger.__index = Logger
function Logger.new(name) return setmetatable({name=name},Logger) end
function Logger:log(msg) print("["..self.name.."] "..msg) end

local Service = {}
Service.__index = Service

function Service.new(name)
  return setmetatable({
    name=name,
    logger=Logger.new(name)  -- delegation
  },Service)
end

function Service:start()
  self.logger:log("starting...")  -- delegate logging
  print(self.name, "running")
end

Service.new("AuthService"):start()

Verifica rapida

Qual è la differenza tra obj:method() e obj.method()?

Riepilogo: metodi di istanza

Riepilogo:

  • Sintassi di chiamata con i due punti: obj:method() == obj.method(obj)
  • Restituisca self per concatenare i metodi
  • Chiami altri metodi: self:otherMethod()
  • Callback: le racchiuda in una closure per preservare self
  • Metodi statici: utilizzi per convenzione la notazione con il punto
  • Preferisca la delegazione all'ereditarietà profonda per una maggiore flessibilità

Domande Frequenti

La lezione «Metodi delle istanze e self» è gratuita?

Sì — il testo completo di «Metodi delle istanze e self» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Lua Academy, passa a CoddyKit PRO. Il corso Lua Academy include 4 lezioni in totale.

Cosa imparerò in «Metodi delle istanze e self»?

Definisca metodi usando la sintassi con i due punti e il parametro implicito self. Eserciti Lua Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Lua Academy?

Non è richiesta alcuna esperienza precedente. Lua Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Metodi delle istanze e self»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Lua Academy?

Sì. Ogni lezione Lua Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Classi tramite metatabelle
  2. Costruttori e new()
  3. Metodi delle istanze e self
  4. Incapsulamento con le closure
← Torna a Lua Academy