Jump to content




Functional OOP in Lua


27 replies to this topic

#21 tesla1889

  • Members
  • 351 posts
  • LocationSt. Petersburg

Posted 19 March 2013 - 02:57 AM

you sandbox the crap out of anything that has to do with metatables

#22 Pharap

  • Members
  • 816 posts
  • LocationEngland

Posted 19 March 2013 - 10:33 AM

View PostElvishJerricco, on 18 March 2013 - 03:10 PM, said:

when I described the table based classes that are easy to hack, I was describing how the standard metatable system works. Just take a look at the tutorial. It explains it all.

A class is a function.

It's very simple actually. And it works flawlessly.
That tutorial is only basic metatable stuff, and it's only one way to use metatables. Some ways are more secure than others and much harder to hack.

It's a bad idea to have classes as functions for several reasons. Constructors fine, classes no.

It does have flaws. For one thing, it has no set protection. If I were to do obj.this = "hello", from now on all functions in the object calling this would be getting 'hello'.
__index only fires when the index isn't found in the table itself, so it's easy enough for external stuff to modify the object and screw things up.

Also to note:
if classes[f] and classes[f].super then
			    new(classes[f].super, obj, ...)
			    local super = obj
			    obj = setmetatable({}, { __index = super })
			    obj.super = super
	    else
			    setmetatable(obj,{__index = fenv})
	    end

f doesn't have to be listed in classes list to be used, which means I could in theory pass in the 'print' function or some native function like setfenv and get some very strange results.

The idea is getting there, but it actually has no more security than using metatables, the only advantage it has is pseudo-inheritance.

#23 ElvishJerricco

  • Members
  • 803 posts

Posted 22 March 2013 - 11:10 AM

View PostPharap, on 19 March 2013 - 10:33 AM, said:

View PostElvishJerricco, on 18 March 2013 - 03:10 PM, said:

when I described the table based classes that are easy to hack, I was describing how the standard metatable system works. Just take a look at the tutorial. It explains it all.

A class is a function.

It's very simple actually. And it works flawlessly.
That tutorial is only basic metatable stuff, and it's only one way to use metatables. Some ways are more secure than others and much harder to hack.

It's a bad idea to have classes as functions for several reasons. Constructors fine, classes no.

It does have flaws. For one thing, it has no set protection. If I were to do obj.this = "hello", from now on all functions in the object calling this would be getting 'hello'.
__index only fires when the index isn't found in the table itself, so it's easy enough for external stuff to modify the object and screw things up.

Also to note:
if classes[f] and classes[f].super then
			    new(classes[f].super, obj, ...)
			    local super = obj
			    obj = setmetatable({}, { __index = super })
			    obj.super = super
	    else
			    setmetatable(obj,{__index = fenv})
	    end

f doesn't have to be listed in classes list to be used, which means I could in theory pass in the 'print' function or some native function like setfenv and get some very strange results.

The idea is getting there, but it actually has no more security than using metatables, the only advantage it has is pseudo-inheritance.

You're pointing out flaws with the objects themselves. The classes are not to blame. But in *any* implementation of OOP in lua, the objects are going to be at risk. That's just the way it is, and the way it's always been. That's why you expect programmers to use the objects wisely.

#24 tesla1889

  • Members
  • 351 posts
  • LocationSt. Petersburg

Posted 23 March 2013 - 02:41 AM

View PostElvishJerricco, on 22 March 2013 - 11:10 AM, said:

--snip--
You're pointing out flaws with the objects themselves. The classes are not to blame. But in *any* implementation of OOP in lua, the objects are going to be at risk. That's just the way it is, and the way it's always been. That's why you expect programmers to use the objects wisely.
so why are you so opposed to metatable OOP then? if you admit that the objects in functional OOP are just as vulnerable, why not choose the more extensible of the two: metatables?

#25 Kingdaro

    The Doctor

  • Members
  • 1,636 posts
  • Location'MURICA

Posted 23 March 2013 - 02:59 AM

To be fair, tesla, it's easy to just combine both methods.

function myAmazingObject(...)
  local obj = {...}
  local mt = {
    __index = obj;
    __call = function(self, props)
      return setmetatable(props, mt)
    end;
  }
  return setmetatable(obj, mt)
end

thing = myAmazingObject(someParam, someOtherParam) {
  boop = 'booooooop';
}

Though I don't know why anyone would ever do this, haha.

#26 tesla1889

  • Members
  • 351 posts
  • LocationSt. Petersburg

Posted 23 March 2013 - 11:08 AM

View PostKingdaro, on 23 March 2013 - 02:59 AM, said:

--snip--
function myAmazingObject(...)
  local obj = {...}
  local mt = {
	__index = obj;
	__call = function(self, props)
	  return setmetatable(props, mt)
	end;
  }
  return setmetatable(obj, mt)
end

thing = myAmazingObject(someParam, someOtherParam) {
  boop = 'booooooop';
}
--snip--

nice syntax lol :D
is javascript on your mind?

#27 Kingdaro

    The Doctor

  • Members
  • 1,636 posts
  • Location'MURICA

Posted 23 March 2013 - 11:15 AM

View Posttesla1889, on 23 March 2013 - 11:08 AM, said:

nice syntax lol :D
is javascript on your mind?

Nah. Mostly sugar.

#28 Pharap

  • Members
  • 816 posts
  • LocationEngland

Posted 23 March 2013 - 04:38 PM

View Posttesla1889, on 23 March 2013 - 02:41 AM, said:

View PostElvishJerricco, on 22 March 2013 - 11:10 AM, said:

--snip--
You're pointing out flaws with the objects themselves. The classes are not to blame. But in *any* implementation of OOP in lua, the objects are going to be at risk. That's just the way it is, and the way it's always been. That's why you expect programmers to use the objects wisely.
so why are you so opposed to metatable OOP then? if you admit that the objects in functional OOP are just as vulnerable, why not choose the more extensible of the two: metatables?

I concur.

It's not the idea of using functions as constructors I oppose, it's that the idea of implementing classes is so that you can 'classify' objects. This means you should be able to clarify the type of the object. This is one of the things metatables attempt. Whilst you cannot name the type of the 'object' (technically you sort of can but it's open to tampering), you can give two tables using the same metatable the same special behaviour. Assuming nobody involved in the use of the program has mal-intent, you can use metatables to properly classify tables in a class-like system.

This can be achieved as thus:
1-Declare a metatable that grants particular behaviour to a table by use of the operator and indexing overiders (__add,__mul,__index,__newindex etc). Adapting the new index feature can be very useful as it allows for typechecking and data protection.
2-Set a metatable's __metatable property to return a string clarifying the type of the object
3-Create a method that is used as a constructor for the 'object', ensuring it sets the metatable of the table it returns to the correct metatable. Ideally you would want to lock off the metatable to prevent it being tampered with (be it to protect the table from misuse or to protect the 'objects' from displaying unintended behaviour)

From there on out, tables with the same metatables would react as they should and attempting to get their metatable would in fact return the name of their type. This is unfortunately open to tampering unless the metatable functions are sealed off, as someone else could simply make a new metatable with the same string used as its __metatable property, thus rendering the classification system useless.

To further improve such a system, ideally the metatable would keep 'true' tables in a table within itself, and the constructor would both add to this table and return a different table. The tables held in the metatable would be indexed with the tables returned by the constructor (the 'key' tables) so that the 'true' tables hold the actual data whilst the 'key' tables are merely used as a way of interfacing with the data. This would be more of a tampering-resistant system, however it would not solve the capability for multiple tables to use the same __metatable property. The only real way to prevent that is to tamper with the default get and set metatable functions (ie make setmetatable not accept two metatables with the same __metatable property).

So in reality the capability is all there, it just requires a lot of tampering which may have a negative impact on speed or memory usage, but it's worthwhile if you want to prevent tampering at all costs or at least try to replicate the class systems of other languages.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users