Ylikirjoittaminen ja polymorfismi
Ylikirjoittakaa emoluokan metodeja ja toteuttakaa ajonaikainen polymorfinen metodikutsu.
Ylikirjoittaminen ja polymorfismi on ilmainen Lua Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Lua Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Lua Academy-kurssilla on yhteensä 4 oppituntia.
Metodin ylikirjoittaminen
Lapsiluokka ylikirjoittaa isäntäluokan metodin määrittelemällä samannimisen metodin. Kun metodia kutsutaan lapsiolion kautta, lapsiluokan versio suoritetaan. Isäntäluokan versio on edelleen käytettävissä muodossa Parent.method(self).
local Shape={} Shape.__index=Shape
function Shape:area() return 0 end
function Shape:describe() print(type(self).." area="..self:area()) end
local Circle={} Circle.__index=Circle
setmetatable(Circle,{__index=Shape})
function Circle.new(r) return setmetatable({r=r},Circle) end
function Circle:area() return math.pi*self.r^2 end
local Square={} Square.__index=Square
setmetatable(Square,{__index=Shape})
function Square.new(s) return setmetatable({s=s},Square) end
function Square:area() return self.s^2 end
Circle.new(5):describe()
Square.new(4):describe()Polymorfinen hajautus
Polymorfismissa erityyppiset oliot vastaavat samaan viestiin eri tavoin. Funktio, joka hyväksyy minkä tahansa "shape"-olion ja kutsuu metodia :area(), toimii kaikilla muototyypeillä — kukin käyttää omaa toteutustaan.
local shapes={
Circle.new(3),
Square.new(4),
Circle.new(1),
}
local total=0
for _,shape in ipairs(shapes) do
total=total+shape:area()
end
print(string.format("Total area: %.2f",total))Ankkatyypitys
Lua käyttää ankkatyypitystä: jos oliolla on metodi, se toimii. Muodollista rajapintamäärittelyä ei tarvita. Funktio, joka kutsuu metodia :speak(), toimii minkä tahansa speak-metodin sisältävän olion kanssa luokasta riippumatta.
local function makeNoise(obj)
if type(obj.speak)=="function" then
obj:speak()
else
print("(silent)")
end
end
local Duck={speak=function(self) print("Quack!") end}
local Robot={speak=function(self) print("Beep boop!") end}
local Rock={}
makeNoise(Duck) -- Quack!
makeNoise(Robot) -- Beep boop!
makeNoise(Rock) -- (silent)Operaattorien polymorfismi
Metametodit, kuten __add, mahdollistavat operaattorien polymorfismin. Eri tyypit voivat toteuttaa operaattorille + oman semantiikkansa, kunhan ne määrittelevät __add-metodin.
local Vec2={} Vec2.__index=Vec2
Vec2.__add=function(a,b) return Vec2.new(a.x+b.x,a.y+b.y) end
Vec2.__tostring=function(v) return "("..v.x..","..v.y..")" end
function Vec2.new(x,y) return setmetatable({x=x,y=y},Vec2) end
local Color={} Color.__index=Color
Color.__add=function(a,b)
return Color.new(math.min(255,a.r+b.r),math.min(255,a.g+b.g),math.min(255,a.b+b.b))
end
function Color.new(r,g,b) return setmetatable({r=r,g=g,b=b},Color) end
print(tostring(Vec2.new(1,2)+Vec2.new(3,4))) -- (4,6)Visitor-suunnittelumalli
Visitor-suunnittelumalli erottaa operaatiot olioista. Operaatio "vierailee" eri tyyppisissä olioissa ja kutsuu tyypin mukaista metodia. Käytä sitä operaatioihin, joiden on vaihdeltava tyypin mukaan ilman tyyppien muokkaamista.
local function printInfo(obj)
local mt = getmetatable(obj)
if mt == Circle then
print(string.format("Circle r=%.1f area=%.2f",obj.r,obj:area()))
elseif mt == Square then
print(string.format("Square s=%.1f area=%.2f",obj.s,obj:area()))
end
end
for _,s in ipairs({Circle.new(3),Square.new(4)}) do
printInfo(s)
endRajapintataulukko
Määritä rajapinta metodinimien taulukkona. Tarkista ennen polymorfista käyttöä, että olio toteuttaa kaikki vaaditut metodit.
local function implements(obj, interface)
for _, method in ipairs(interface) do
if type(obj[method]) ~= "function" then
return false, "missing: "..method
end
end
return true
end
local Drawable = {"draw","resize","move"}
local Widget = {
draw=function(self) print("draw "..self.type) end,
resize=function(self,w,h) self.w,self.h=w,h end,
move=function(self,x,y) self.x,self.y=x,y end,
type="button"
}
local ok,err = implements(Widget,Drawable)
print(ok,err) -- true nilMetodin olemassaolon tarkistus
Tarkista ennen valinnaisen metodin polymorfista kutsumista, että oliolla on kyseinen metodi. Näin voidaan tarjota valinnaisia ominaisuuksia ilman yhteistä kantaluokkaa.
local function maybeUpdate(obj, dt)
if type(obj.update)=="function" then
obj:update(dt)
end
end
local objects={
{x=0,y=0,update=function(self,dt) self.x=self.x+10*dt end},
{x=0,y=0}, -- no update
{x=0,y=0,update=function(self,dt) self.y=self.y+5*dt end},
}
for _,o in ipairs(objects) do maybeUpdate(o,1) end
for _,o in ipairs(objects) do print(o.x,o.y) endTyyppiin perustuva hajautustaulukko
Käytä if/elseif-ketjujen sijaan hajautustaulukkoa: yhdistä tyyppinimet käsittelijäfunktioihin. Tämä on taulukko-ohjatun polymorfismin malli.
local handlers={
number = function(v) return "num:"..v end,
string = function(v) return "str:\"".."..v.."\"" end,
boolean = function(v) return "bool:"..(v and "T" or "F") end,
table = function(v) return "tbl:#"..tostring(#v) end,
}
local function describe(v)
local h=handlers[type(v)]
return h and h(v) or "unknown"
end
print(describe(42))
print(describe("hello"))
print(describe({1,2,3}))Kovariantit palautusarvot
Lapsiluokan metodit voivat palauttaa isäntäluokan metodeja tarkempia tyyppejä (kovariantti palautusarvo). Lua on dynaamisesti tyypitetty, joten tämä on luontevaa — lapsiluokan factory palauttaa lapsiolion, ei vain isäntäoliota.
local Base={} Base.__index=Base
function Base.new() return setmetatable({type="base"},Base) end
function Base:copy() return Base.new() end
local Child={} Child.__index=Child
setmetatable(Child,{__index=Base})
function Child.new(extra)
local self=setmetatable({type="child"},Child)
self.extra=extra; return self
end
function Child:copy() return Child.new(self.extra) end -- covariant
local c=Child.new("hello")
local c2=c:copy()
print(c2.extra,getmetatable(c2)==Child) -- hello truePolymorfismin yhteenveto
Lua-polymorfismi käytännössä: sama metodinimi, erilainen toiminta tyypin mukaan. Se voidaan toteuttaa metatauluihin perustuvalla olio-ohjelmoinnilla, ankkatyypityksen tarkistuksilla tai hajautustaulukoilla. Muodollista rajapintajärjestelmää ei tarvita — johdonmukaiset metodien nimeämiskäytännöt riittävät.
-- Three ways to achieve polymorphism:
-- 1. Metatable inheritance + method override
-- 2. Duck typing: just call it if it exists
-- 3. Dispatch table: map type -> handler
local function area(shape)
-- Duck typing approach:
assert(type(shape.area)=="function","needs area()")
return shape:area()
end
print(area({area=function() return 16 end})) -- 16Polymorfismi-kysymys
Miten polymorfismi toimii Luassa?
Kertaus: ylikirjoittaminen ja polymorfismi
Ylikirjoita isäntäluokan metodit määrittelemällä ne uudelleen lapsiluokassa. Lua ratkaisee kutsut alhaalta ylöspäin __index-ketjun kautta, mikä mahdollistaa luonnollisen ajonaikaisen polymorfisen hajautuksen.
Opi Lua tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 40
- Oppitunnit
- 159
Usein kysytyt kysymykset
Onko oppitunti ”Ylikirjoittaminen ja polymorfismi” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Lua Academy-oppimispolun 3 oppituntia, myös oppitunnin “Ylikirjoittaminen ja polymorfismi”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Lua Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Ylikirjoittaminen ja polymorfismi”?
Ylikirjoittakaa emoluokan metodeja ja toteuttakaa ajonaikainen polymorfinen metodikutsu. Harjoittelet Lua Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Lua Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Lua Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Ylikirjoittaminen ja polymorfismi”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Lua Academy-oppitunnilla?
Kyllä. Jokainen Lua Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Yksiperintä __index-ketjutuksella
- Emoluokan metodien kutsuminen superilla
- Mixin-rakenteet
- Ylikirjoittaminen ja polymorfismi