Class library (OOP) - Help Thread
Since the class would implement the respective interface, you know that the core functionality remains consistent between the classes. Therefore, it would be easy to test out the different implementations and see which one does what you want.
The fact that interfaces would have the "I' says immediately that they are interfaces. I didn't use an "I" for the List interface, because I was using the Java List interface as a basis and wanted to preserve the naming. Also, with Array and Vector already devolped, there is no need for a "list" class.
Add OOP to your scripts via the Class Library. Check out my scripts.
Most of my DOM interfaces, probably because they didn't start off as interfaces, handle almost all of the processing internally, and really only require the calling class to construct the actual objects and add any non-official DOM functions. Should I be moving the functions out to the calling class and just referencing them from the interface, as is seen in Coin (save for its single static function)? Or is it acceptable to keep a large number of statics in an interface?
An interface is meant to be a shell. For example, the List interface defines functions which are used to manipulate lists. Then, the implementing classes (e.g. Array and Vector) implement these functions.So how far do you go building functionality into the interface, as opposed to leaving the functionality for the calling class to implement?
The only functions that should be defined in the interface are functions that are "final" (using java terminology). A final function is a function that can't be overridden. For example, the List_copy function is defined directly, because it performs the necessary task - there is no need to override it.
An interface, by design, is meant to "share" functionality. It is meant to define functions which a set of similar classes share.
I'm not sure I understand the question, but if you are asking if you should be creating an interface that implements the functions, I can only ask 1) what would the implementing class implement, and 2) why not just keep it as a class?Most of my DOM interfaces, probably because they didn't start off as interfaces, handle almost all of the processing internally, and really only require the calling class to construct the actual objects and add any non-official DOM functions. Should I be moving the functions out to the calling class and just referencing them from the interface?
Interfaces, and inheritence, when added, have the overhead of a dynamic call and the function call to Class_call / Class_Scall. These functions must "figure out" which class to call. Did you run the two examples of the List_test (List_test1.ahk and List_test2.ahk)? If not, I would suggest doing so - this shows the added overhead in using interface functions.
By statics, do you mean static functions. If so, static functions should be "rare"; at least, in my programming experience, rarely do I need a static function. For example, the getWorth function is static because a nickel, regardless, is worth 5 cents. Also, by making it a function (instead of, maybe, a constant in the constant function), it can be used as the "useFunction" paramater of the get and getAddress functions in the list interface (and implementing classes). For example, this is used in the CoinPurse object, to return the total amount of money in the CoinPurse via its getWorth function, which in turn uses the getWorth function in the coin interface.Or is it acceptable to keep a large number of statics in an interface?
Add OOP to your scripts via the Class Library. Check out my scripts.
The reason I'm using interfaces at all for the DOM is to follow the DOM specification... I want to create interfaces, and a set of default implementing classes, but allow anyone to create their own implementing classes however they see fit, as well.
Some of the interfaces truly need to be interfaces to function properly, I believe. Most of them directly correspond to real objects, however, and are just made into interfaces to separate the definition of the functions from the actual implementation of them.
I'm seeing the use in moving almost all of my logic outside of the interface and leaving it a shell, as it should be. Thanks again for helping clear that up.
That would make it more useful to be able to call other classes without knowing the class name.
For instance, my DOM class needs to call a certain function within the class of an object it is passed in one of its methods.
Rather than calling Class_getClassName and then manually creating the function string, I'd like to be able to just do something like:
Class_call("canSet", Object, param1, param2, etc...)
Currently this will throw an error. Instead of a check to make sure there is an underscore in the name, perhaps there should just be a function to remove everything before the underscore in the function name to normalize it, and then figure out which class to call and append the class name and underscore again?
The reason it throws an error is that Class_call and Class_Scall have checks to verify that the specified class object implements the class specified by the function name. That's why interface functions pass A_ThisFunc for the first parameter. Since the function name is File_Func and File is the name of the interface, everything up to the first "_" is the interface name. Then, it verifies the specified object / class implements the interface.perhaps there should just be a function to remove everything before the underscore in the function name to normalize it, and then figure out which class to call and append the class name and underscore again?
However, I can write another function, without this check - how about "invoke" (as seen in the COM library).
Class_invoke(Object, "canSet", param1, param2, etc...)This would call the canSet function in the class (as specified by Object). It would still make use of the reserved value ("C1@5s", internally, because it needs to know how many parameters are passed, so that only that number of parameters are passed in the dynamic call.
Since interfaces are just starting, should I reverse the parameters (object, then paramater) to have them match the format used by COM_Invoke (for consistency)? This would apply to the newly added functions Class_invoke and Class_Sinvoke and the existing Class_call and Class_Scall. This will break scripts that use Class_call and Class_Scall, but since interfaces just began, if the change is made, now is better than later. Also, it only affects the interfaces themself - not the calling of an interface function. So, it would be very easy to modify.
Add OOP to your scripts via the Class Library. Check out my scripts.
I'm using Class_call in about 25 interfaces right now, but it would be a simple search and replace operation in each of them.
For all four functions, you can call Class_callError to see if the call resulted in an error, and the error (if any, or 0 otherwise) will be returned. I've update the page on Interfaces to reflect the changed parameter order. I'll add a page for Class_invoke / Class_Sinvoke shortly.
The List and Coin interface were updated to use the new syntax. I used the below RegEx to swap the two parameters. This will swap the first two parameters for all Class_call and Class_Scall functions. It assumes that "A_ThisFunc" is the first parameter, which it should be if you followed the format used in the List and Coin interface.
;spacing (around parameters) and name for the second parameter are maintained. ;This RegEx works for both Class_call and Class_Scall Find: (Class_S?call)\((\s*)(A_ThisFunc)(\s*),(\s*)(\w+)(\s*)(\)|,) Replace: $1($2$6$4,$5$3$7$8
Download the updated zip.
Add OOP to your scripts via the Class Library. Check out my scripts.
And thanks also for invoke. I haven't been able to test yet, but I'm using it as required already in the DOM.
To get a parameter of an object from an external class, I'd like to be able to pass Class_invoke(Object, "getSomeParam"), for instance. Right now it throws an error because it's looking for a variable reference instead.
The function name isn't ByRef - the parameters are, though. Is this what you meant?Is it possible for invoke to accept the function name as a string instead of a ByRef?
The parameters are ByRef so that if you call a function that has any ByRef parameters, calling the function via Class_invoke will work as expected.
I can change this, so that the parameters are no longer ByRef; however, this would mean Call_invoke won't work correctly when calling a function with ByRef parameters. However, it will allow calling Class_invoke by passing a value, instead of only allowing variable references.
This is the function's signature
Class_invoke(ClassObject, FunctionName, ByRef arg1 = "C1@5s", ByRef arg2 = "C1@5s", ByRef arg3 = "C1@5s", ByRef arg4 = "C1@5s", ByRef arg5 = "C1@5s", ByRef arg6 = "C1@5s")
Add OOP to your scripts via the Class Library. Check out my scripts.
Yes, I was referring to the parameters. More often than not I'll be passing variables to Class_invoke for its parameters, but it would be nice not to have to.
You bring up a good point, though--it would also be expected to work when passing a byref, so changing it might not be the best option either.
I can't think of any graceful way to get around it; I could just assign the values to variables and use them with Class_invoke how it is now, or perhaps a second function could be created without byrefs, maybe Class_sinvoke (for string invoke) or something?
Now that I understand its purpose, it does seem like a good idea to leave the invoke function using ByRefs as you've designed it to do.
Example
Class_invoke(Object, Function, arg1 := "Parameter 1", arg2 := 0xC001D06)
If this solution isn't satisfactory, I can add the forementioned Class_Vinvoke and Class_SVinvoke functions. However, if any parameters need to be ByRef, Class_invoke / Class_Sinvoke would be the one you would need to call; you could use the above solution for the parameters that are values.
Add OOP to your scripts via the Class Library. Check out my scripts.
It would be great if Class could automagically determine if a parameter should be a byref and pass it accordingly, but I don't think it's possible currently.