Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properties #18

Closed
Shadowblitz16 opened this issue Dec 19, 2021 · 15 comments
Closed

Properties #18

Shadowblitz16 opened this issue Dec 19, 2021 · 15 comments

Comments

@Shadowblitz16
Copy link

Shadowblitz16 commented Dec 19, 2021

Can you support getter and setter properties by appending get- or set- at the beginning of a function?

@flamendless
Copy link

@Shadowblitz16 this is outside the scope of classic.

What you want is easily doable but it's specific to your needs so it won't make sense adding it to this lib.

@Shadowblitz16
Copy link
Author

Shadowblitz16 commented Dec 19, 2021

How would I do this myself then?

I know it has to do with __index and __newindex

@Shadowblitz16 Shadowblitz16 changed the title properties Properties Dec 19, 2021
@flamendless
Copy link

You can create your own properties table and do a for loop for that generating your own getter and setter

self.props = {x = 0, y = 0}
for k in pairs(self.props) do
  self["set_" .. k] = function(self, value)
     self.props[k] = value
  end
  -- do the same but for get
end

@capr
Copy link

capr commented Dec 20, 2021

@Shadowblitz16 at the other end of the spectrum of simplicity there's https://github.com/luapower/oo/blob/master/oo.md (450 LOC)

@Shadowblitz16
Copy link
Author

Shadowblitz16 commented Dec 20, 2021

something like this?

function Object:extend()
  local cls = {}
  for k, v in pairs(self) do
    if k:find("__") == 1 then
      cls[k] = v
    end
  end
  for k, v in pairs(self) do    
    if type(self[k]) == "table" then
      local name = k:sub(1,1):upper()..k:sub(2)
      self["set" .. name] = function(self, value)
        self[k] = value
      end
      self["get" .. name] = function(self)
        return self[k]
      end
    end
  end
  cls.__index = cls
  cls.super = self
  setmetatable(cls, self)
  return cls
end

and these would be overridable?

Edit:
wait I don't see how this connects the variable to the setter and getter methods
I am essentially am looking for is making all variable private with __index and _newindex and only allowing public access to properties aka methods with set and get in from of them or function aka methods without set and get in from of them

@capr
Copy link

capr commented Dec 20, 2021

Uhm, not really. So you actually want virtual properties like you want foo.x = 5 to call foo:set_x(5) behind the scenes, and x = foo.x to call foo:get_x() ?

If so, you need to set __index to a function (not a table) that will do the dispatching to the getters of your properties at runtime, and also __newindex to a function that will do the dispatching to the setters. Look at the code I linked, see if it makes sense.

@Shadowblitz16
Copy link
Author

ya basically but I also want foo.x to not be accessible outside of the class

@capr
Copy link

capr commented Dec 20, 2021

By foo.x you mean the actual variable that's holding the value, not the property, right? Cuz the property will be called foo.x, where you chose to store the value of x is a separate problem.

@Shadowblitz16
Copy link
Author

Shadowblitz16 commented Dec 20, 2021

yes the variable name would still be accessible outside the class but outside the class it would be a property and inside it would be a variable

This is what I tried before but it didn't work like I expected...

function Object:__index(key)
  local name   = key:sub(1,1):upper()..key:sub(2)
  local getter = rawget("get"..name)
  if getter ~= nil then
    return getter(self)
  elseif getmetatable(self) == self then
    return rawget(self, key)
  end
end

function Object:__newindex(key, value)
  local name   = key:sub(1,1):upper()..key:sub(2)
  local setter = rawget("get"..name)
  if setter ~= nil then
    return setter(self, value)
  elseif getmetatable(self) == self then
    return rawset(self, key, value)
  end
end

@capr
Copy link

capr commented Dec 20, 2021

That you can't have. Lua doesn't have the concept of inside or outside the class. What you can have is a field that by convention you make private (like eg. _x), and in the setter you set it, but otherwise you pretend it isn't there. You can also have a field that's only visible by the setter (an value from outer scope, aka an up-value) but that's it.

@Shadowblitz16
Copy link
Author

You can also have a field that's only visible by the setter (an value from outer scope, aka an up-value) but that's it.

what do you mean by this? it sounds interesting

@capr
Copy link

capr commented Dec 20, 2021

Ok try this https://gist.github.com/capr/5f78e61759dbf97f45d427131f8a0d5f

is the minimum amount of modification that I could do to this code to get you what you want

@capr
Copy link

capr commented Dec 20, 2021

I still recommend the 450 LOC version I linked as there are many caveats with OO systems, but in the end I really just recommend trying to understand how the mechanism works and DIY. You may immediately ask yourself how to make the getters and setters inheritable, how to avoid concatenating strings which creates garbage on each field access, etc.

Also, I just have to say this: I wouldn't recommend OOP at all in Lua unless you're making a UI system with a DOM. If you're doing OOP in Lua, you're missing out.

@Shadowblitz16
Copy link
Author

Ok try this https://gist.github.com/capr/5f78e61759dbf97f45d427131f8a0d5f

is the minimum amount of modification that I could do to this code to get you what you want

This is close but I don't think this is what I want completely.
private_x would be cleared after the scope exist so it couldn't hold state.

I still recommend the 450 LOC version I linked as there are many caveats with OO systems, but in the end I really just recommend trying to understand how the mechanism works and DIY. You may immediately ask yourself how to make the getters and setters inheritable, how to avoid concatenating strings which creates garbage on each field access, etc.

I did look at that version and I think its too much for me...

also wouldn't the getters and setters be inheritable by default? they are just methods I thought that you could do...

self.super:set_x(x)

@capr
Copy link

capr commented Dec 20, 2021

private_x would be cleared after the scope exist so it couldn't hold state.

Not true. It's called an up-value. You should read on Lua's lexical scoping.

Maybe I should mention before I go to bed, since this is getting waaay out of scope of this issue anyway: Lua's metamethods and lexical scoping are advanced topics, don't get deceived by the small code size of this lib, you really have to study it carefully to understand what's going on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants