g_Data={}


A =
{
    id = 0,
    nNum = 0,

}
-- construct a
function A:New(o)

 o = o or {};

    o.id = o.id  or 0;
    o.nNum =  o.nNum or 0;


    setmetatable(o, self);
 self.__index = self;
    if o.id ~= 0 then
      g_Data[o.id] = o;
    end

 return o
end

function A:printA()
    print(" A ------ id:",self.id,"Num:",self.nNum)
end

function A:printB(n)
    return self.nNum +n;
end

function A:printM(n)
    return " A:printM"

end

B= A:New
{
    name ="";
}

-- construct b

function B:New(o)

 o =  A:New(o) or {};

    o.id = o.id  or 0;
    o.nNum =  o.nNum or 0;
    o.name = o.name or "";

    setmetatable(o, self);
 self.__index = self;

 return o
end

function B:printA()
   print(" B ------ id:",self.id,"Num:",self.nNum,self.name)
end

function B:printB(n)
  --  print(" BBBB ------ id:",self.id,"Num:",self.nNum)
     local m = A.printB(self,n)
     m = m +1000;
     return m;
end

C = B:New
{

}
-- construct c

function C:New(o)

 o =  B:New(o) or {};


    setmetatable(o, self);
 self.__index = self;

 return o
end

function C:printA()
   print(" C ------ id:",self.id,"Num:",self.nNum,self.name)
end

function C:printB(n)
  --  print(" BBBB ------ id:",self.id,"Num:",self.nNum)
     local m = A.printB(self,n)
     m = m +2000;
     return m;
end

function test()

local a = A:New
{
    id =1,
    nNum = 1,
}
local b = A:New
{
    id =2,
    nNum = 2,
}

a:printA() -- call A:printA()

b:printA() -- still call A:printA()

g_Data[1]:printA()

 

for i = 10,15 do
    A:New
    {
        id =i,
        nNum = i*i,
    }
end


for i = 16,20 do
    B:New
    {
        id =i,
        nNum = i*i,
        name = "test" .. i;
    }
end
for i = 21,25 do
    C:New
    {
        id =i,
        nNum = i*i,
        name = "test" .. i;
    }
end

  print(">>>>>>>>>>>>>>:")
     for index,a in pairs(g_Data) do
         --print("index",index,"a.id", a.id, "a[id]",a["id"])
         a:printA() -- Polymorphism call
     end

  print(">>**************************>>>>>>>>>>>>")
     for index,a in pairs(g_Data) do
         print("index ",index," n:", a:printB(10),"A:printB:",A.printB(a,10),a:printM())

    a:printA() -- Polymorphism call and qualified call 

     end

  print(">>>>>>>>>>>>>>")
end

test();