Is this a bad OOP design for lua? [closed] - oop

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I've discovered (and written) a way to object oriented programming in lua in a functional fashion instead of the standard metatable method. It carries much more functionality (no pun intended) but I'm afraid it might dent performance. My goal is to experiment with servers written in lua and I wanted to use this OOP solution. Anyways here's my class.lua which holds the functions for creating new objects and subclasses.
local classes = setmetatable({}, {__mode = "k"}) -- Allow the GC to empty this as needed.
function class(f, super)
classes[f] = {super = super}
end
function new(f, obj, ...)
local fenv = getfenv(f)
if type(obj) ~= "table" then
error("bad argument: expected table, got " .. type(obj) , 2)
end
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
obj.this = obj
setfenv(f, obj)
f()
setfenv(f, fenv)
if obj.init then
obj.init( ... )
end
return obj
end
Usage is fairly simple. Take the following example:
function Person()
local privateVar = math.random()
age, name, gender = nil, nil, nil
function init(age, name, gender)
this.age = age
this.name = name
this.gender = gender
end
function getAge()
return age
end
function getName()
return name
end
function getGender()
return gender
end
function getPrivateVar()
return privateVar
end
end
And to create the object
obj = new(Person, {}, "John", 30, "male")
Subclassing is also simple
function Female()
function init(name, age)
super.init(name, age, "female")
end
end
class(Female, Person)
Note that you only have to call a function to make something a class if you want to subclass.
When you call new, you pass in the class, object, and arguments. The object's metatable is set to have an index of the class's original environment. Then the super is determined and created. Then the class function is run to create all instance values. Next, init is called.
One advantage of this over metatables are that other code can't change the class and have it change all instances of that class that already exist and that will exist. Now the only way to do something like that is to swizzle and hack around in environments to make sure all references to the class refer to the hacker's dummy class.
On top of that, it supports private variables. Just declare them locally in your class function and you're good to go.
But I'm wondering if the fact that it creates all the instance methods once for every instantiation is going to cause performance problems. Will this eat memory? What can go wrong here?
Also, there's an issue. While this supports multiple inheritance, if you call a super method, and the super calls a method, it will call the method of the super class, not the instantiated class. Any ideas how to make it call from the instantiated class?

Related

Is Kotlin "pass-by-value" or "pass-by-reference"?

As I know Java is pass-by-value from this post. I am from Java background I wonder what Kotlin is using for passing values in between. Like in Extensions or Methods etc.
Every time I hear about the "pass-by-value" vs "pass-by-reference" Java debate I always think the same. The answer I give: "Java passes a copy (pass-by-value) of the reference (pass-by-reference)". So everyone is happy. I would say Kotlin does the same as it is JVM based language.
UPDATE
OK, so it's been a while since this answer and I think some clarification should be included. As #robert-liberatore is mentioning in the comments, the behaviour I'm describing is true for objects. Whenever your methods expect any object, you can assume that the JVM internally will make a copy of the reference to the object and pass it to your method. That's why having code like
void doSomething(List<Integer> x) {
x = new ArrayList<Integer>()
}
List<Integer> x = Arrays.asList(1, 2, 3);
doSomething(x);
x.length() == 3
behaves like it does. You're copying the reference to the list, so "reassigning it" will take no effect in the real object. But since you're referring to the same object, modifying its inner content will affect the outer object.
This is something you may miss when defining your attributes as final in order to achieve immutability. You won't be able to reassign them, but there's nothing preventing you from changing its content
Of course, this is true for objects where you have a reference. In case of primitives, which are not a reference to an object containing something but "something" themselves, the thing is different. Java will still make a copy of the whole value (as it does with the whole reference) and pass it to the method. But primitives are just values, you can't "modify its inner values". So any change inside a method will not have effect in the outer values
Now, talking about Kotlin
In Kotlin you "don't have" primitive values. But you "do have" primitive classes. Internally, the compiler will try to use JVM primitive values where needed but you can assume that you always work with the boxed version of the JVM primitives. Because of that, when possible the compiler will just make a copy of the primitive value and, in other scenarios, it will copy the reference to the object. Or with code
fun aJvmPrimitiveWillBeUsedHere(x: Int): Int = x * 2
fun aJvmObjectWillBeUsedHere(x: Int?): Int = if (x != null) x * 2 else 1
I'd say that Kotlin scenario is a bit safer than Java because it forces its arguments to be final. So you can modify its inner content but not reassign it
fun doSomething(x: MutableList<Int>) {
x.add(2) // this works, you can modify the inner state
x = mutableListOf(1, 2) // this doesn't work, you can't reassign an argument
}
It uses the same principles like Java. It is always pass-by-value, you can imagine that a copy is passed. For primitive types, e.g. Int this is obvious, the value of such an argument will be passed into a function and the outer variable will not be modified. Please note that parameters in Kotlin cannot be reassigned since they act like vals:
fun takeInt(a: Int) {
a = 5
}
This code will not compile because a cannot be reassigned.
For objects it's a bit more difficult but it's also call-by-value. If you call a function with an object, a copy of its reference is passed into that function:
data class SomeObj(var x: Int = 0)
fun takeObject(o: SomeObj) {
o.x = 1
}
fun main(args: Array<String>) {
val obj = SomeObj()
takeObject(obj)
println("obj after call: $obj") // SomeObj(x=1)
}
You can use a reference passed into a function to change the actual object.
The semantics is identical to Java.
In Java, when you have an instance of an object, and you pass it to a method, that method can change the state of that object, and when the method is done, the changes would have been applied to the object at the call site.
The same applies in Kotlin.
For primitives value is passed, and for non-primitives a reference to the object is passed. I'll explain with an example:
The code:
fun main() {
var a = 5
var b = a
a = 6
println("b = $b")
}
prints: b = 5
Kotlin passes the value of a to b, because a is a primitive. So changing a afterwards won't impact b.
The code:
fun main() {
var a = Dog(5)
var b = a
a.value = 6
println("b = ${b.value}")
}
class Dog (var value: Int)
prints b = 6, because this time a is not a primitive and so the reference to the object (Dog) was passed to b and not its value. Therefore changing a would affect all objects that point to it.
In Java primitive types like int, float, double, boolean are passed to a method by value, if you modify them inside the receiver method they doesn't change into the calling method. But if the property/variable type isn't a primitive, like arrays of primitives or other classes when they are changed inside the method that receive them as parameter they also change in the caller method.
But with Kotlin nothing seems to be primitive, so I think all is passed by reference.
This might be a little bit confusing.
The correct answer, IMHO, is that everything passes by reference, but no assignment is possible so it will be similar to passing by value in C++.
Note that function parameters are constant, i.e., they cannot be assigned.
Remember that in Kotlin there are no primitive types. Everything is an object.
When you write:
var x: Int = 3
x += 10
You actually create an object of type Int, assign it the value 3, and get a reference, or pointer, named x.
When you write
x += 10
You reassign a new Int object, with the value 13, to x. The older object becomes a garbage (and garbage-collected).
Of course, the compiler optimizes it, and creates no objects in the heap in this particular case, but conceptually it is as explained.
So what is the meaning of passing by reference function parameters?
Since no assignment is possible for function parameters, the main advantage of passing by reference in C++ does not exist in Kotlin.
If the object (passed to the function) has a method which changes its internal state, it will affect the original object.
No such method exists for Int, String, etc. They are immutable objects.
No copy is ever generated when passing objects to functions.
Bear in mind, am quite new to Kotlin. In my opinion, primitives are passed-by-value, but objects are passed-by-reference.
A primitive passed to a class works by default, but if you pass an object from a list, for example, and that object changes, the class object changes too. Because, in fact, it is the same object.
Additionally, if objects gets removed from the list, the class object IS STILL A REFERENCE. So it can still change due to references in other places.
Example below explaines. You can run it here.
fun main() {
val listObjects = mutableListOf(ClassB(), ClassB(), ClassB())
val listPrimitives = mutableListOf(111, 222, 333)
val test = ClassA()
test.ownedObject = listObjects[0]
test.ownedPrimitive = listPrimitives[0]
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listObjects[0].isEnabled = true
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listPrimitives[0] = 999
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
}
class ClassA {
var ownedObject: ClassB = ClassB()
var ownedPrimitive: Int = 0
}
class ClassB {
var isEnabled = false
}
Since Kotlin is a new language for JVM, like Java it is pass-by-value. The confusing part is with object, at first it looks like that it is passed-by-reference but the actuality is that the reference/pointer itself is pass-by-value (a copy of a reference is passed to a method) hence when a method receives a reference to an object, the method can manipulate the original object.

bad argument #2 to 'setmetatable' (nil or table expected)?

I currently stuck on this with a corona app I'm creating.
I have a file structure like below:
App -> Classes -> Objects -> Ships
In the App folder is the main.lua, menu.lua, level.lua and Class.lua. In the Classes folder there is Object.lua. In Objects, ship.lua and finally in the Ships are my different ships i.e. player and enemy.
I followed this tutorial and my code is almost completely identical to his (bar player and enemys classes), but still am receiving this error in the Class.lua is
"bad argument #2 to 'setetatable'(nil or table expected)"
The code I receive the error on is
function Class(Super)
Super = Super or Base
local prototype = setmetatable({}, Super) -- receive error here
prototype.class = prototype
prototype.super = Super
prototype.__index = prototype
return prototype
end
Base = Class()
function Base:new(...)
local instance = setmetatable({}, self)
instance:initialize(...)
return instance
end
function Base:initialize() end
function Base:get()
local Instances = self.Instances
if (not Instances[1]) then local obj = self:new() end
return table.remove(Instances, 1)
end
function Base:dispose()
table.insert(self.Instances, self)
end
I've tried changing the classes and changing the "setmetatable({},Super)" to "setmetatable(Super, self), putting all the classes in one file, I've read the lua docs, requiring the Class.lua in the mai, menu and the level.lua etc. and nothing has worked.
Any help would be greatly appreciated.
Thanks
function Class(Super)
Super = Super or Base
local prototype = setmetatable({}, Super) -- receive error here
prototype.class = prototype
prototype.super = Super
prototype.__index = prototype
return prototype
end
Base = Class()
Follow the execution of the code above.
You declare a function Class and then call it (and assign its returned value to Base).
Step through the execution of Class from the Base = Class() line.
function Class(Super)
The function takes one argument named Super
Super = Super or Base
You are allowing the Super argument to be nil/unpassed by using a default value of Base.
This call Base = Class() is not passing a value so this line Super = Super or Base has Super as nil and so evaluates to Super = nil or Base however the global Base is also nil as it has not yet been assigned to so you get Super = nil.
local prototype = setmetatable({}, Super)
This line then attempts to use Super (assigned from the line before) only it is, as we just saw, nil hence your error.
The bit from the tutorial that you missed (or at least missed in your posted snippet) is the crucially important local Base line above the Class function definition.

When to use the trait Instance() constructor, and questions about the traitsUI tutorial code

I have a question regarding the traitsui tutorial by Gael Varoquaux.
In code snippet 7 he makes a CaptureThread class for producing a thread for taking images from a camera. He also make a Camera class.
class TextDisplay(HasTraits):
string = String()
view = View(Item('string', show_label=False, springy=True, style='custom'))
class CaptureThread(Thread):
def run(self):
#self.display is set outside the class definition by the caller
self.display.string = 'Camera started\n' + self.display.string
n_img = 0
while not self.wants_abort:
sleep(0.5)
n_img += 1
self.display.string = ' %d image captured\n' % n_img \
+ self.display.string
self.display.string = 'Camera stopped\n' + self.display.string
class Camera(HasTraits):
start_stop_capture = Button()
display = Instance(TextDisplay)
capture_thread = Instance(CaptureThread)
view = View( Item('start_stop_capture', show_label=False))
def _start_stop_capture_fired(self):
if self.capture_thread and self.capture_thread.isAlive():
self.capture_thread.wants_abort = True
else:
self.capture_thread = CaptureThread()
self.capture_thread.wants_abort = False
self.capture_thread.display = self.display
self.capture_thread.start()
I have two questions about this code:
1) Why in the Camera class definition does he make capture_thread a Trait, by calling Instance(CaptureThread)? CaptureThread is just a thread class, why should we make a trait instance out of it?
2) In the CaptureThread class he makes use of a field self.display.string and of self.wants_abort. These two fields are not passed in via a constructor method, rather they are assigned outside of the class definition by the Camera class. Is this the best practise? Since if the user of the CaptureThread forgot to set these two fields, then an error would occur. Are there some sensible guidelines to know when I can assign thing like that, or I should use a constructor to assign them?
I hope that these questions make sense, and that this is the right place to ask them!
Thanks, labjunky
capture_thread = Instance(CaptureThread) doesn't make an instance of CaptureThread. It is more of a declaration that gets consumed by the Camera class when the class gets created. It tells that Camera class that it will have an attribute named capture_thread that should be an instance of CaptureThread or None and will default to None. This default lets the "test if self.capture_thread is initialized, otherwise create it" logic in _start_stop_capture_fired() a little cleaner, at least to some people's tastes.
For threading.Thread subclasses, yes, it's one idiomatic way to do it, though not the only one. Thread already has a specific __init__ implementation, and you could override it to do something else, but it is understandable that the author would avoid doing so in this case.
This is not the idiomatic way to initialize HasTraits subclasses which is indeed to use keyword arguments.

Class structure in Lua/Corona

So I'm working on a game in Lua and I'm trying to use metatables and classing but I think I'm importing my PHP knowledge and doing things slightly sideways.
-- Basic Monster
Monster = {}
function Monster:new(newX, newY)
local newMonster = {x = newX, y = newY}
setmetatable(newMonster, {__index = Monster})
return newMonster
end
function Monster:moveTo(newX, newY)
self.x = newX
self.y = newY
end
function Monster:takeDamage()
self.hitPoints = self.hitPoints - playerWeapon.damage
if self.hitPoints <= 0 then
self.die()
end
end
function Monster:tap()
self.takeDamage()
end
function Monster:die()
self.removeSelf()
end
--Groblin
Groblin = {}
setmetatable(Groblin, {__index = Monster})
function Groblin:new(newX, newY)
local groblin = display.newImage('assets/images/goblin.png');
groblin.hitPoints = 4
physics.addBody(groblin, 'static')
gameGroup.insert(groblin)
return groblin
end
I'm basically looking to be able to spawn several different types of monsters, and retain some base class functionality for them, but I'm uncertain in the above example how I tie in the base class to the Groblin class I made as I feel like I blew out that subclass altogether by what I'm doing inside of Groblin:new.
If you want classes that you can subclass, try using middleclass. It's not very trivial to do subclasses in standard lua and middleclass has taken care of the boilerplate.
Also, make use of local -- use it anywhere it can be used.
A simple way to do this with your example would be:
function Groblin:new(newX, newY)
local groblin = Monster:new( newX, newY )
setmetatable(groblin, {__index = Groblin})
groblin.image = display.newImage('assets/images/goblin.png');
-- ...
return groblin
end
Use the base class ":new()" method to construct the object and then add the unique fields for the subclass. This insures the base class is properly constructed. Re-setting the metatable to "Groblin" in the subclass constructor insures that any methods defined for the Groblin subclass are called if available, and where the Groblin table does not re-define a method the superclass method will be called.
It probably is better to use a library that provides a consistent approach for object creation and subclassing, but hopefully that gives you a better idea of how to do things manually.
Check out http://www.lua.org/pil/16.2.html for inheritance.
Pay a little attention on the explanation of how the use of self in Account:new works out best while SpecialAccount extends Account.
I generally follow a little different approach than the mentioned in above link. In the above approach -
SpecialAccount = Account:new()
s = SpecialAccount:new{limit=1000.00}
You are calling Account:new() twice, and more problem arises when Acoount:new() does some validaiton on constructor parameters and throws exceptions. For ex: ensuring that the limit passed in non-nil.
So I follow this
SpecialAccount = setmetatable({__index = Account})
Does the trick of allowing superclass constructor to be used in subclasses.
PS: I prefer to treat new function as a constructor. It essentially does the same job.

Creating classes dynamically in matlab

Given a structure, is there a way to create a class in MATLAB? Take for instance
>> p = struct(); p.x = 0; p.y = 0;
>> p
p =
x: 0
y: 0
>> name = 'Point'
name =
Point
What I would like to do, is given a string containing the name of the class and a struct with containing the fields I would like to create a class without having to write a file explicitly writing the definition.
Right now if we use class(p) we will obtain struct. What I want to do is create an object of the type Point so that when I do class(obj) then I get Point.
Any ideas how to accomplish this besides writing a file in MATLAB with the class definition and then executing it?
Either you have specific functionality (methods) associated with the Point class as opposed to e.g. the Line class, in which case you should write out the classes by hand, anyway, or you can make a single dynamicprops class that can have dynamically created properties, and unless you really need to call a method named class, you much simplify your life by calling classname instead.
classdef myDynamicClass < dynamicprops
properties (Hidden)
myClass %# this stores the class name
end
methods
function obj = myDynamicClass(myClassName,varargin)
%# synopsis: obj = myDynamicClass(myClassName,propertyName,propertyValue,...)
%# myClassName is the name of the class that is returned by 'classname(obj)'
%# propertyName/propertyValue define the dynamic properties
obj.myClass = myClassName;
for i=1:2:length(varargin)
addprop(obj,varargin{i})
obj.(varargin{i}) = varargin{i+1};
end
end
function out = classname(obj)
out = obj.myClass;
end
end
end
I don't know of any way of creating objects dynamically, so I'd say the answer to your question is no. However, to solve your problem, I would propose something very similar to what Mikhail said:
Work with a struct with fields x, y and classname:
p.x=0;
p.y=0;
p.classname='Point';
and then write a function myclass(x) which returns x.classname. If for some reason you need to use class() you could even overload it with your own function which checks if x is one of your special structs and calls builtin('class', x) otherwise:
function out=class(varargin)
if nargin==1 && isstruct(varargin{1}) ... #check if we were given a struct
&& isfield(varargin{1}, 'classname') ... #...which contains a field classname
&& ischar(varargin{1}.classname) %# ... which is a string
out=varargin{1}.classname; %# ok, our special case :-)
else
out=builtin('class',varargin{:}); %# normal case - call builtin class()
end
One solution that I've used in the past is to write a MATLAB function that takes this information (i.e. the class name and fields) and writes an M-file containing the required classdef construct.
This works well if you're using this information to describe a prototype that you want to expand later.