Lua Academy · Pelajaran

Kaedah Tika dan self

Takrifkan kaedah menggunakan sintaks titik bertindih dan parameter self tersirat.

Pelajaran 3 daripada 412 langkah

Kaedah Tika dan self ialah pelajaran Lua Academy percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Lua Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Lua Academy merangkumi sejumlah 4 pelajaran.

self ialah Tika

Apabila anda memanggil obj:method(), Lua menghantar obj sebagai argumen pertama secara automatik. Mengikut konvensyen, parameter ini dinamakan self. Melalui self, kaedah mengakses data tika dan memanggil kaedah lain.

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

Rantaian Kaedah

Kembalikan self daripada kaedah untuk membolehkan rantaian: obj:method1():method2():method3(). Setiap panggilan mengembalikan objek yang sama, lalu membolehkan gaya lancar. Ini paling sesuai untuk kaedah yang mengubah keadaan.

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

Memanggil Kaedah Lain

Kaedah boleh memanggil kaedah lain pada tika yang sama melalui self:otherMethod(). Ini menggalakkan penggunaan semula kod dalam sesuatu kelas. Pembantu persendirian boleh berupa fungsi tempatan biasa yang menerima self secara jelas.

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

Amaran Penggantian Kaedah

Menetapkan medan tika dengan nama yang sama seperti kaedah kelas akan menyembunyikan kaedah tersebut untuk tika itu. Ini biasanya pepijat — berhati-hatilah apabila nama medan tika mungkin bertembung dengan nama kaedah.

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 dalam Panggilan Balik

Menghantar kaedah sebagai panggilan balik menyebabkan self tersirat hilang. Balut kaedah dalam penutupan untuk menangkap 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

Kaedah Statik berbanding Kaedah Tika

Kaedah statik dipanggil pada kelas, bukan pada tika. Kaedah ini tidak mempunyai self (atau menerima kelas sebagai self). Dalam Lua, tiada perbezaan formal — mengikut konvensyen, gunakan . (bukan :) untuk kaedah statik.

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

Kaedah Mixin

Tambahkan kaedah daripada jadual mixin kepada sesuatu kelas tanpa pewarisan formal. Ini ialah gubahan rata: salin atau rujuk fungsi mixin ke dalam jadual kelas.

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())

Kaedah Abstrak

Lua tidak menguatkuasakan kaedah abstrak, tetapi anda boleh mentakrifkan kaedah kelas asas yang menimbulkan ralat, lalu memaksa subkelas menggantikannya. Ini ialah konvensyen untuk "mesti diganti".

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

Jadual Kaedah

Untuk kelas yang mempunyai banyak kaedah, susunkannya dalam kumpulan mengikut fungsi. Semua kaedah dalam jadual yang sama berkongsi carian metajadual yang sama, tetapi anda boleh membahagikannya mengikut tanggungjawab menggunakan ruang nama kecil.

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)

Delegasi berbanding Pewarisan

Utamakan delegasi (memegang rujukan) berbanding rantaian pewarisan yang mendalam. Sesuatu kelas boleh mewakilkan tugas kepada objek lain dan bukannya mewarisinya, sekali gus mengekalkan gandingan yang rendah dan memastikan setiap kelas kekal fokus.

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()

Semakan Pantas

Apakah perbezaan antara obj:method() dengan obj.method()?

Imbas Kembali: Kaedah Tika

Ringkasan:

  • Sintaks panggilan bertitik bertindih: obj:method() == obj.method(obj)
  • Kembalikan self untuk rantaian kaedah
  • Panggil kaedah lain: self:otherMethod()
  • Panggilan balik: balut dalam penutupan untuk mengekalkan self
  • Kaedah statik: gunakan tatatanda titik mengikut konvensyen
  • Gunakan delegasi berbanding pewarisan mendalam untuk fleksibiliti
Percuma untuk bermula

Pelajari Lua dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
40
Pelajaran
159

Soalan Lazim

Adakah pelajaran “Kaedah Tika dan self” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Lua Academy, termasuk “Kaedah Tika dan self”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Lua Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Kaedah Tika dan self”?

Takrifkan kaedah menggunakan sintaks titik bertindih dan parameter self tersirat. Anda berlatih Lua Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Lua Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Lua Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Kaedah Tika dan self” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Lua Academy ini?

Ya. Setiap pelajaran Lua Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Kelas melalui Metajadual
  2. Pembina dan new()
  3. Kaedah Tika dan self
  4. Pengkapsulan dengan Closure
← Kembali ke Lua Academy