__index for sugar [Solved]

hello !

I have an instance of class (called obj after) who contains {w=10, h=10}.
I want access by 2 way : obj.w and obj.width.
I know about the __index function, but i don’t know how write this =/

(Warning: only tested on desktop lua.)

a = {}
mt = {}
mt.__index = function(t,k)
  if k == "width" then 
    return k.w
  end
end
mt.__newindex = function(t,k,v)
  if k == "width" then
    rawset(t,"w",v)
  else
    rawset(t,k,v)
  end
end
setmetatable(a,mt)

Testing:

a.w = 10
print(a.w)
print(a.width)
a.width = 20
print(a.width)
print(a.w)

(Added)

Note: if your initial object is an instance of a class then you don’t want to overwrite its metatable as I do above because it already has some useful stuff in it. So you’d need to so mt = getmetatable(a) first instead of mt = {}. I’d also test to see if __index or __newindex are blank first - I don’t remember what Codea’s class does to objects’ metatables.

Hm… am i missunderstanding you or have you just written:

w=10, h=10

without the self thing. Only the Main class variables does not have to contain self before them selves. So the only way to access he value of obj.w is to write “self.” before “w”.
I hope I understood you right :slight_smile:

thanks a lot @Andrew_Stacey !
and @MMGames, i have write a “bad example”. A better example (with solution)

Object = class(ObjectFather)
Object.sugars = {width="w", height="h"}

function Object:init()
   ObjectFather.init(self)
   self.w = 10
   self.h = 10
end

------------------- At the end of file -------------------
function Object:__index(k)
   if Object.k then return Object.k end
   for sugarKey, key in pairs(Object.sugars) do
      if k == sugarKey then
         return self[key]
      end
   end
end
function Object:__newindex(k,v)
   for sugarKey, value in pairs(Object.sugars) do
      if k == sugarKey then
         rawset(self, key, v)
      end
   end
   rawset(self, k, v)
end
-------------------------------------------------------

```


Now :

~~~
obj = Object()
print(obj.w, obj.width) -- > 10, 10
obj.w = 15
print(obj.width) -- > 15
~~~

Are you sure you want the line: if Object.k then return Object.k end? Are you setting defaults as class variables?

@Andrew_Stacey

I think this is the last solution with a recusive system.

Object = class(ObjectFather)
Object.sugars = {width="w", height="h", x="pos.x", y="pos.y"}
 
function Object:init()
   ObjectFather.init(self)
   self.w = 10
   self.h = 10
   self.pos = {}
   self.pos.x = 0
   self.pos.y = 0
end
 
------------------- At the end of file -------------------
function Object:__index(k)
   if Object[k] then return Object[k] end
   for sugarKey, key in pairs(Object.sugars) do
      if k == sugarKey then
         local arr = explode(".", key)
         if #arr == 1 then
            return self[key]
         else
            local result = self
            for _, v in pairs(arr) do
               result = result[v]
            end
            return result
         end
      end
   end
end
function Object:__newindex(k,v)
   for sugarKey, value in pairs(Object.sugars) do
      if k == sugarKey then
         local arr = explode(".", key)
         if #arr == 1 then
            rawset(self, key, v)
         else
            local result = self
            for _, v in pairs(arr) do
               beforeLastResult = result
               result = result[v]
            end
            rawset(beforeLastResult, arr[#arr], v)
         end
      end
   end
   rawset(self, k, v)
end
-------------------------------------------------------

function explode(div,str) -- credit: http://richard.warburton.it
  if (div=='') then return false end
  local pos,arr = 0,{}
  -- for each divider found
  for st,sp in function() return string.find(str,div,pos,true) end do
    table.insert(arr,string.sub(str,pos,st-1)) -- Attach chars left of current divider
    pos = sp + 1 -- Jump past current divider
  end
  table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider
  return arr
end


```

Yes, I was just about to tell you that the class is the metatable for all of its instances so it’s enough to define Class:__index and Class:__newindex.

@Andrew_Stacey, this is not that I do ?

@HyroVitalyProtago Yes, that is what you do. That was the meaning behind the “Yes, I was …”. It was to be read as “I see that you’ve figured this out for yourself, but I’ll mention it anyway”.

Ah, okay. Thanks !