Nobody says that metatables are needed for OOP. They're useful, not essential.
Metatables allow you to hide data. I can break all of your careful coding very easily:
local dog = Chihuahua.New()
dog.sName = nil --Oops.
dog.GetName = nil --Oops.
It would also allow other dubious constructs, such as storing other data in the object: dog.newVar = foo
.
OOP is about more than just inheritance. Good OOP should also incorporate encapsulation, to maintain the integrity of an object from accidental misuse. Metatables allow you to do this by using an empty table for the main table and filtering all setting and getting through __index
and __newindex
metamethods. This way, only the object can store data in the actual table. And only the object can retrieve it unless you provide explicit access.