Classes and adding properties

I am trying to start using the included luabind classes and have a couple of questions about adding properties. I can add methods/functions fine as shown in the rasterbar and renoisesnippets which also cover inheritance. Here the properties seem to be inside of functions, such as self.can_fly = true in the renoise snippets.

However running oprint() on a renoise.song() object (that I believe is an luabind class?), gets a nested properties printout aswell as methods. Running the same on the snippet examples just gets the methods as you would expect I guess.

class: Song
properties:
 artist
  artist_observable
 comments
 ...etc

methods:
 __STRICT
 add_track_to_group
 can_redo
 can_undo
 ..etc

I have tried for example:

class 'MyClass'
 
  --oprint() cannot see this
  MyClass.foo = "bar"
 
  --oprint() will see this fine
  function MyClass:__init(name)
 self.name = name
  end

So my questions are:

-how are these oprint() visible, properties added and what do i need to know about them?

-are they private?

-and is calling them controlled by methods within the class?

“oprint” lists class methods and properties of a class. But properties are not class members, but getter/setter wrapper functions created with the global function “property” in Lua. Those are used internally to wrap C++ getter/setter functions, which then act like members of a class.

Also if you do: MyClass.foo=“bar” then you’re adding a string property to the !class! object and not to a class’ instance.

You probably wanted to do something like:

obj = MyClass("qwe")
obj.foo = "bar"

in your example.

Here’s a small test to demonstrate the global “property” function:

class 'MyClass'
  
  function MyClass:__init(name)
    self.name = name
  end
  
  MyClass.bar1 = function(obj)
    print "MyClass.bar1 called"
  end
  
  function MyClass:bar2() 
    print "MyClass.bar2 called"
  end
  
  MyClass.property_test = property(
    function(obj)
      print(("MyClass.getter called (%s)"):format(obj.name))
      return obj.name
    end, 
    function(obj, value)
      print(("MyClass.setter called (value=%s)"):format(value))
      obj.name = value
    end)

local obj = MyClass("Hans")

print(obj.name) -- "Hans"
print(obj.property_test) -- "Hans"

obj.name = "Wurst"
print(obj.name) -- "Wurst"
print(obj.property_test) -- "Wurst"

obj.property_test = "Wurst2"
print(obj.property_test) -- "Wurst2"
print(obj.name) -- "Wurst2"

obj:bar1() -- "MyClass.bar1 called"
obj:bar2() -- "MyClass.bar2 called"

oprint(obj)

If you do not provide a setter function above, the property will be read-only and an error is fired when trying to assign a value to that property.

Such properties are quite likely not very useful when creating classes in Lua. They are mostly useful for the C++ <-> Lua wrappers only.

Thank you taktik,

I have been playing around with that code in testpad and think I have got my head around it. From what it seems there is no automatic encapsulation/privacy given to the self.name property. In your example you can assign to it via:

--direct access
obj.name = "Wurst"

--access via property(fn(),fn())
obj.property_test = "Wurst2"

So I guess if wanted, encapsulation would have to be coded by hand with local variables? (no need to read through all the following link, it`s just on my to-study list):

http://www.troubleshooters.com/codecorn/lua/luaoop.htm

So for overall basic picture, the included luabind class system has?:

-Operator overloading

-Inheritance

-Constructors

but lacks:

-encapsualtion (private variables)

-other more advanced oo stuff


Also Just for the thread the link to the property() function, documented for luabind:

http://www.rasterbar.com/products/luabind/docs.html#properties

So I guess if wanted, encapsulation would have to be coded by hand with local variables? (no need to read through all the following link, it`s just on my to-study list):

So for overall basic picture, the included luabind class system has?:

-Operator overloading
-Inheritance
-Constructors

but lacks:

-encapsualtion (private variables)
-other more advanced oo stuff

Yes. Private and protected scopes for member-/functions can not be realized with the luabind classes. But there are various ways to implement this in Lua with other OO class alike approaches (see for example http://lua-users.org/wiki/ObjectOrientationTutorial - Closure-based objects).
But IMHO this usually isn’t worth it: You can always invent your own convention to mark your members or functions private by for example prefixing them with an underscore or “internal_” or whatever else. Or even simpler: describe in comments what is public and what not.

Unless you’re writing interfaces for others this usually also is no big deal, cause you always can workaround your own conventions and restrictions anyway :wink:

And when writing interfaces there are other techniques in Lua available too, like splitting public and private interfaces or data into separate lua packages instead of dealing with multiple scopes within classes. Also packages in Lua can contain local private functions or data, which can not be “seen” when loaded somewhere with require. See http://www.lua.org/pil/15.2.html for more info.

Thanks taktik, that clears up a lot here, including the underscores I`ve seen other people use for normal variables in their classes.

Im not into making any APIs myself at the moment! but I have been looking at C++ on and off and its useful to be able to contrast and get all the principles clear. I have also recently bought bluecats PlugnScript which uses the Angelscript language (C++ syntax, minus pointers).

Hopefully will get my head around this OOP stuff finally!

Just a related side question: What are the double underscore properties/ methods that come up in oprint(some renoise.object) like __STRICT?