Fields as Objects - Actions

Monkey Forums/Monkey Programming/Fields as Objects - Actions

NoOdle(Posted 2012) [#1]
I wrote an Action class a while ago, it allows you to create various pre coded actions like moving to a location, rotating to an angle etc etc.

I wanted to simplify this as it required a new action to specifically handle each field. I could also find myself adding new actions every project I work on.

I decided to write some test code and I came up with this. There are two classes, one for floats and one for ints. These objects can be used as fields for any class. This allows me to interpolate or adjust any field that makes use of the int and float class. If a field doesn't need to be part of an Action it can use the regular Float / Int declaration.

Can anybody see any problems with doing it this way? Is there a better/simpler way to achieve the same thing?

Heres a quick runnable example to show what I mean:




muddy_shoes(Posted 2012) [#2]
There's a trade-off for performance. Your method is going to mean that every access to the internal properties will go through method calls or a dereference. Also, as you're using objects instead of primitives, there will be a trade-off on memory. There may also be a GC hit because of the increase in objects to be handled and the deeper tree.

Further, because you're now passing around references to internals you've potentially got issues with something holding onto those references or using them in nefarious ways. If it's just you using the code then this might not be a problem.

It's hard to offer a better solution as you seem to be looking for something very generic. Much of what you're doing I do with either tweens or via strategies. However, neither of these can just be attached to operate on arbitrary values within objects.

I would suggest creating accessor objects rather than actually making the internal value an object and passing that out. Unfortunately, Monkey doesn't let you create function objects in a compact way so you'd have to create a class for each property. If you pretty much want everything to be accessible then that's going to be painful.


NoOdle(Posted 2012) [#3]
Thank you for the information, you have confirmed some of my worries about doing it this way.

Also, as you're using objects instead of primitives


What do you mean by primitives? A float array? Thinking about it now, it would be cleaner that way, not sure why I didn't do that.

It's hard to offer a better solution as you seem to be looking for something very generic. Much of what you're doing I do with either tweens or via strategies. However, neither of these can just be attached to operate on arbitrary values within objects.


Yea it is frustrating, I've done this in Obj-C but without the hack and I was hoping to achieve something similar with monkey. It's also a shame there isn't an equivalent of selectors, they would be very helpful too.

Im pretty sure this action won't need to be used that often, I have actions for all the properties in my framework so its only really for projects and classes that introduce new ones. The action can be used sparingly, for example it makes sense to only use it when firing at the same time as other actions. I'll optimise the code some more when I implement it.. I also need to code a way to make an action call a function by name. I have a couple of ideas of how this can be achieved....


ziggy(Posted 2012) [#4]
This is not an issue on Java or .net AFAIK, also the way current incremental c++ GC is designed will play nice with this design but making the properties real properties is a better idea IMHO.

Class FloatValue
Private
	Field value : Float

Public
	Method New( v : Float )
		Self.value = v
	End Method

	Method Value : Float() Property
		Return Self.value
	End Method
	
End Class
Function Main()
    Local myVal:FloatValue = New FloatValue(44.5)
    Print myVal.Value
End



Samah(Posted 2012) [#5]
@NoOdle: It's also a shame there isn't an equivalent of selectors, they would be very helpful too.

It's ugly, and probably slow, but you could easily implement selectors/function pointers with reflection.

Obj-C:
@interface Foo : NSObject
-(void)someMethod;
-(void)bar;
@end

@implementation Foo
-(void)init
{
	self = [super init];
}

-(void)someMethod
{
	...
}

-(void)bar
{
	SEL somesel = @selector(someMethod);
	[self performSelector:somesel];
}
@end


Monkey:
[monkeycode]Class Foo
Method someMethod:Void()
...
End

Method bar:Void()
' somesel is a selector/fp for the "someMethod" method in class Foo
Local somesel:MethodInfo = GetClass(Self).GetMethod("someMethod", [])
' equivalent to calling: Self.someMethod()
somesel.Invoke(Self, [])
End
End[/monkeycode]
I haven't done Objective-C in a while, and I haven't tried compiling either of them. ;)


Samah(Posted 2012) [#6]
From your post in the other thread:
@NoOdle: What would you prefer to use, Interface based callback or reflection invoking? I think the reflection option would be a cleaner implementation but Interfaces will probably be faster. Guess I'll know more when I do some testing.

After some scrutinising of the reflection process, it actually shouldn't be too bad. Reflection in Monkey creates a new class for every class, function, method, etc., and the code is highly specific.

Java's reflection (which isn't used in Monkey's implementation) is reliant on ClassLoader performance and needs to perform all the introspection at runtime. Monkey pregenerates all the reflection information.

I'll make up a test case for it, and you might be surprised. Perhaps this is the way forward? ;)