AutoHotkey Community

It is currently May 26th, 2012, 5:09 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 259 posts ]  Go to page Previous  1 ... 5, 6, 7, 8, 9, 10, 11 ... 18  Next
Author Message
 Post subject:
PostPosted: February 26th, 2009, 2:56 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
I found a cool use for wrapper.

I'm about 1/2-way done with my XML class (at least, the initial release).

The class utilizes MSXML via the COM stdlib. Rather than work directly with MSXML nodes as COM objects, I created a wrapper class named XMLNode

By default, it simply stores the reference to the COM node object, and returns the reference with its getValue function (for direct use).

The destroy function releases the COM object automatically (if it still exists), so the user never has to worry about that.

This way, within the XML object, I store both a docNode value (which unwraps to the COM object for the whole document), and a Nodes vector, which contains references to all node objects created from that XML object.

When the XML object is destroyed, the nodes vector should also be destroyed, which will destroy each of the nodes in the vector, which in turn releases the COM object referencing the node.

In this way, the user only ever HAS to worry about destroying the XML object when they're finished. Of course, they are welcome to destroy individual nodes as they go along as well (which will happen automatically where appropriate too).

I'm really loving these new features. I think it will allow me to make the XML class very powerful and simple to use (relatively speaking).

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 26th, 2009, 10:25 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Question: Is inheritance a possibility?

I could really use it in my XML library. Currently it's taking a lot of work to maintain dynamic functions in my parent class, and duplicate function calls in my inheriting classes. It would be cool if it could actually be inherited :)

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 3:56 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
It depends what you need. Some can only be emulated because AHK isn't OOP by nature. So, what needs do you have? Knowing them, I can figure out the correct implementation.

Update:
It seems there is now an isFunc function. This will help greatly in adding inheritence - makes the code neater, at least. This does mean that when I add inheritence, it will require the latest version of AHK to be used.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 4:36 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
isFunc seems well suited for helping with this, I think.

The biggest hassle in setting up my XML library is that I have a parent class, XMLNode, which has a lot of methods that are utilized by other classes, such as XMLEntity, XMLNotation, XMLComment, XMLAttribute, etc...

All of them inherit the methods and properties from XMLNode, and some of them add their own. For me to emulate that without inheritance, however, I had to create duplicate functions in each child class which reference the parent function, and the parent functions use Class_getClassName to get information from child classes where appropriate.

I don't know how yet, but would it be possible to somehow inherit the functions of another class without specifying each function in each sub-class? Even better, would it be possible to do so without extra dynamic function calls in my class function (to determine which class called the function). It seems that ultimately that should be handled by the class library, but maybe I'm wrong there.

Property inheritance would be really nice, but since I'm working mostly with COM objects, most of my get/set functions work directly with COM, so it wouldn't help me too much for my current needs.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 4:41 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
bmcclure wrote:
I don't know how yet, but would it be possible to somehow inherit the functions of another class without specifying each function in each sub-class? Even better, would it be possible to do so without extra dynamic function calls in my class function (to determine which class called the function). It seems that ultimately that should be handled by the class library, but maybe I'm wrong there.

Can you give a broad example of what you need? Can you apply the example to my shape and circle example, since I can "genericfy" it better.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 5:14 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Ok, an example of what I'd like based on Rectangle. Since it's such a simple example, it seems less important, but hopefully you'll get the gist:

Rectangle class has a width and height, and an area function which multiplies them.

Lets say you had several variations of that Rectangle class, maybe needing to store different types of things inside them. The purpose is less important than the practice in this case I think, but regardless, you create a second class called RectangleStorage, as one of those variant types. It also has a width, and height, and additionally a storage object for whatever purpose it's needed for.

Now the RectangleStorage class creates its own objects, but since it is also a rectangle, and needs a width and height value, and an area function, it would be nice if those could be inherited from the Rectangle class.

Some way to tell the Class library to treat RectangleStorage as a Rectangle. Then, in the RectangleStorage class, you simply have your storage value (which isn't present in the Rectangle class), and of course your required Class functions, and the rest is inherited from Rectangle.

It would be cool if you could override that inheritance by creating a function of the same name in the inheriting class, too (so a local function overrides an inherited one).

I can't think of exactly how it would work, or even the best way to explain it in terms other than my direct needs, heh. Let me know if I should give further clarification on what I mean, or what your thoughts are on this.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 5:51 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Ok. Let me see if I'm understanding the needs. First off, a pet peeve of mine, "less important" should never be used as a synonym for "simple example"; it is these "simple examples" that let us generize into functionality. Pet peeve aside, let's continue.

1) If you wanted to call Rectangle_area via a call to RectangleStorage_area - without creating a RectangleStorage_area function, this can't be done. The easy fix is to create a RectangleStorage_area function which calls Rectangle_area. The two functions MUST have the same parameters, and any ByRef parameters would need to be the same. You can, however, use different default values, and reorder any parameters - just pass them in the correct order when calling the base class' (rectangle's) function. For consistency though, it would make more sense to preserve order.

Ex.
Code:
BaseClass_someFunction(BaseClassObject, arg1, ByRef arg2, arg3, arg4 = 0)


You would have this for the subclass. All mandatory (non-optional) MUST have values passed, but they need not be args. Ex.

Code:
SubClass_someFunction(SubClassObject, arg1, ByRef arg2)
{
    ;"5" is passed as arg3, and arg4 will use the default value (0)
    return BaseClass_someFunction(SubClassObject, arg1, arg2, "5")
}


2) To inherit values: Store the base classes built-in values first, then add any you want - remember to update the built-in size. Because there is no type checking, Rectangle_getHeight will return the "b1b" member - 1st word, 2nd byte, and return a UShort value - regardless of the object's Class. If you make sure that RectangleStorage sets the height in the same place, you can call Rectangle_getHeight on a RectangleStorage object, and return the height. To call RectangleStorage_getHeight, use the method from (1) to create such a function.


This seems like the easiest way, because I'm still not sure what behavior you need. If you are thinking to allow calling RectangleStorage_getHeight and it calls Rectangle_getHeight, you need to create such a function.

My suggestion for inheritence would be: make a copy of the base class' AHK file, remane it the the subclass, and add to it - that's inheritence. Change the function names to the new class name, and add your own values and functions to it. This allows use of the built-in functions and values of the base class in your subclass. As far as user-defined values, they would have to copy the functionality they wanted. The benefit is that value "1" (first user-defined value) works for the base class and the subclass - provided you set the correct built-in size for your subclass; likewise, since the base class values appear in the subclass (in the same position), you can call the base class methods with a subclass object and it will work fine. Problems exist, though, calling user-defined functions in the base class using a subclass object (if those values are not defined in the subclass).


As an example, color is the first user-defined value for Rectangle. If a user wanted to set the color for a RectangleStorage object, they could copy this function, change the name, and it would work as expected. Calling Rectangle_setColor OR RectangleStorage_setColor would do the same thing. Also, passing a Rectangle to either would work the same as well, since it uses the built-in size to know where the first user-defined value is (i.e the offset).

So, "inheritence" may not be needed, unless you have some need that isn't met by this solution. Now, "virtual functions" (as called in C++, at least), might be useful. For example, calling Rectangle_setHeight and passing a RectangleStorage object would be fine, and work. But for the Shape_draw example function and passing a Circle object, it might be desired to call Circle_draw (if it exists), instead.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 6:03 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Quote:
My suggestion for inheritence would be: make a copy of the base class' AHK file, remane it the the subclass, and add to it - that's inheritence.


While I see your point, that's precisely what I'd like to avoid. Inheritance to me means that the inheriting class inherits a current copy of the parent class at runtime, so that any changes made to one class don't have to be made to every subclass, and without having to duplicate functions in classes. I think that's one of the most useful things about inheritance.

I've already used your method of inheritance in my XML class, but it's extremely tedious creating all those wrapper functions, and I'm just hoping I don't have to do a lot of changing to the parent class in the future, since I'll have to propagate it each time to 10 or 15 other classes.

I didn't realize I could use the get function of one class to get from another class, as long as the parameters are in the same place. That will save some dynamic function calls to use the get method from the correct class, at least.

Thanks.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 6:25 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
For the function definitions, I can't help with that. I know of no way to allow calling RectangleStorage_area and have it call Rectangle_area without RectangleStorage_area being explicitely defined.

I might be able to help with the built-in values problem. This method prevents the need to reorder anything when changing your base class, you only have to add added functions (not values) to your subclass. My thought is this, have the first member of your subclass be an object of the base class.

So you would have a Rectangle object as the first built-in value. Note, this sets the rectangle as an object, but returns the address (so to make sure it doesn't unwrap for wrappers - pass the return to the Rectangle functions). Since the Rectangle object is set as an "obj" type, it will be destroyed with the class (which I think is desired, going to let it bounce for a bit though - if this is not desired, set as a "uint" instead).

Code:
RectangleStorage_getRectangle(RectangleStorageObject)
{
    return Class_getValue(RectangleStorageObject, "b1")
}

RectangleStorage_setRectangle(RectangleStorageObject, RectangleObject)
{
    return Class_setValue(Rectangle, "b1", RectangleObject, "obj")
}


Then, to call Rectangle_area from via RectangleStorage_area:
Code:
RectangleStorage_area(RectangleStorageObject)
{
    RectangleObject := RectangleStorage_getRectangle(RectangleStorageObject)

    return Rectangle_area(RectangleObject)
}


Now, this would be better, right? Now, this method will not allow calling Rectangle_area(myRectangleStorageObject). For this, I would need to think something up. However, it will allow not having to change the subclasses with each change to the base class - just add the additional functions.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 11:38 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Yes actually, I think I may switch my XML functions to do something similar to that in the future. Perhaps have a generic container class for a set of common properties, and include that object in everything that needs them.

On another note, I've posted an early, early, preliminary version of my XML library here.

It's nowhere near perfect yet, but just thought you might be interested to know what people are doing with the Class lib :)

Update: and My IniFile library here :)

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Last edited by bmcclure on March 1st, 2009, 2:57 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 27th, 2009, 8:57 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
I have a local "find" function in my ModList class, because I have a need to allow matching by regex. It was a simple change to support it in my search function.

When you introduced your search functions in Vector, I wanted to replace mine, but I don't think I can make them work with a regex pattern.

Is it possible to add a parameter to allow a regex pattern match to the find functions, or should I just keep my own search functions for that?

My find function uses the following logic:
Code:
if (((type = -1) and (thisValue != "")) or ((type = false) and (searchValue = thisValue)) or ((type = true) and RegExMatch(thisValue, "i)" . searchValue))) {
   found++
   ...
}


I use type (the last parameter in my function) to determine how to search:
-1 to search for all non-Empty values (avoids costly regex call)
false, the default, to search for an exact match (equally fast)
true to search with RegExMatch

There may be a better way, as usual, but just wondering if something similar could be implemented at some point?

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 3rd, 2009, 7:55 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Per my original post in my IniFile topic, and your subsequent message, i would love if you would create a standard Class function to make a class able to be cloned.

In my DOM library, I had to use the name 'cloneNode' in all classes which inherit from DOMNode, but that name is specific to node-related classes.

I think a generic clone function would be good. Class_clone sounds simple and fairly precise. It should accept any class object, and return a new class object (that's created internally) that's identical to the old one.

I think it should be created in such a way that it has one parameter - deep (or recurse), which tells Class whether or not to clone child objects. That's the same method used by the DOM, and it seems logical to me.

Will it be another Class option, like Wrapper, or will all classes be able to be cloned? Will any additional work need to be done to support this in my current classes?

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 3rd, 2009, 8:20 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
bmcclure wrote:
Is it possible to add a parameter to allow a regex pattern match to the find functions

You mean allow specifing a value or a RegEx? The only way that would be backward compatable would pass the negative of the Class object and use it as a toggle. I can't use RegEx only, like your IniFile, because it needs to be able to match numbers (e.g. 0 = -0; 5 = 0x5). Would this be feasible or will someone's head spin?

For example:
Code:
;SearchValue is a value
Vector_indexOf(VectorObject, SearchValue)

;SearchValue is a RegEx
Vector_indexOf(-VectorObject, SearchValue)


bmcclure wrote:
Will it be another Class option, like Wrapper, or will all classes be able to be cloned?

Yes, it will be a Class option (Cloneable).

bmcclure wrote:
Will any additional work need to be done to support this in my current classes?

You have to provide the clone method for the Class.

Currently, the Class object holds no information about its contents or its structure. This is done for performance reasons as Class objects already suffer from performance loss to begin with (over native AHK values).

For this reason, anything that requires knowledge of the Class' structure, whether be it cloning, destroying, etc. cannot be done automatically and requires a function to do it.

However, the function will be fairly simple. Basic types "clone" automatically when storing them elsewhere. I'm adding a Clone method to the Legacy Wrappers, and Vector and Array will clone its contents by calling the clone method for each of their objects. If the object is not cloneable, the same object will be used, and the clone function will return false (0) to signify that only a partial clone could be done.

bmcclure wrote:
I think it should be created in such a way that it has one parameter - deep (or recurse), which tells Class whether or not to clone child objects. That's the same method used by the DOM, and it seems logical to me.

Seems logical to me too, thanks for the suggestion.

How is DOM done? Does passing "true" make it a deep clone and "false" make a shallow one?

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 3rd, 2009, 8:30 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Yep, DOM requires that the 'deep' value be specifies as true or false. Here's their description:

deep of type boolean
If true, recursively clone the subtree under the specified node; if false, clone only the node itself (and its attributes, if it is an Element).

Obivously the DOM-specific portion of that (regarding Elements) has no bearing here, but I like the idea of copying only the object itself by default. However, since this is not necessarily built on a tree structure, like Nodes are, how would it work best? Maybe the 'deep' parameter specifies whether to traverse into vectors and other container objects to clone them or not?

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 3rd, 2009, 8:39 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Oh, my work with DOM brought up another question I had.

As long as I don't make the class a wrapper, is it ok to have a getValue function in it that doesn't represent the unwrapped object?

Attributes in DOM, for instance, have a 'value' attribute, so to follow the standards I would need to create getValue and setValue functions. Just making sure that won't affect anything, as long as I don't make the class a wrapper?

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 259 posts ]  Go to page Previous  1 ... 5, 6, 7, 8, 9, 10, 11 ... 18  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 2 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group