Lua

Contributed by Chris Rathman

Lua Script (polymorph.lua)


-- use fallback to do inheritance dispatch
function Inherit(object, field)
   if field == "parent" then return nil end
   if type(object.parent) ~= "table" then return nil end
   return object.parent[field]
end
setfallback("index", Inherit)

function makeShape(newx, newy)
   return {
      x = newx,
      y = newy,

      -- accessors for x & y
      getX = function (self) return self.x end,
      getY = function (self) return self.y end,
      setX = function (self, newx) self.x = newx end,
      setY = function (self, newy) self.y = newy end,

      -- move the x & y position of the object
      moveTo = function (self, newx, newy)
         self:setX(newx)
         self:setY(newy)
      end,
      rMoveTo = function (self, deltax, deltay)
         self:moveTo(self:getX() + deltax, self:getY() + deltay)
      end,

      -- virtual draw method
      draw = function (self) end
   }
end

function makeRectangle(newx, newy, newwidth, newheight)
   return {
      parent = makeShape(newx, newy),
      width = newwidth,
      height = newheight,

      -- accessors for the width & height
      getWidth = function (self) return self.width end,
      getHeight = function (self) return self.height end,
      setWidth = function (self, newwidth) self.width = newwidth end,
      setHeight = function (self, newheight) self.height = newheight end,

      -- draw the rectangle
      draw = function (self)
         write(format("Drawing a Rectangle at:(%d,%d), width %d, height %d\n",
            self:getX(), self:getY(), self:getWidth(), self:getHeight()))
      end
   }
end

function makeCircle(newx, newy, newradius)
   return {
      parent = makeShape(newx, newy),
      radius = newradius,

      -- accessors for the radius
      getRadius = function (self) return self.radius end,
      setRadius = function (self, newradius) self.radius = newradius end,

      -- draw the circle
      draw = function (self)
         write(format("Drawing a Circle at:(%d,%d), radius %d\n",
            self:getX(), self:getY(), self:getRadius()))
      end
   }
end

function TryMe()
   -- set up some shape instances
   scribble = {makeRectangle(10, 20, 5, 6), makeCircle(15, 25, 8)}

   -- iterate through the array and handle shapes polymorphically
   local i = 0
   while i < 2 do
      i = i + 1
      scribble[i]:draw()
      scribble[i]:rMoveTo(100, 100)
      scribble[i]:draw()
   end

   -- access a rectangle specific function
   arect = makeRectangle(0, 0, 15, 15)
   arect:setWidth(30)
   arect:draw()
end

TryMe()

Running the code

Note: The fallback mechanism for inheritance is included
      in a seperate script in the etc directory.

lua etc/fallback.lua polymorph.lua

Output

Drawing a Rectangle at:(10,20), width 5, height 6
Drawing a Rectangle at:(110,120), width 5, height 6
Drawing a Circle at:(15,25), radius 8
Drawing a Circle at:(115,125), radius 8
Drawing a Rectangle at:(0,0), width 30, height 15

Chris Rathman / Chris.Rathman@tx.rr.com