JassHelper Help

Operator making

Jasshelper allows you to declare custom operators for your structs, these operators would then be converted to method calls, vJass currently allows operators for <, >, array set and array get.

The official name for this process (In wikipedia and books) is operator overloading. In the case of vJass, An overloaded operator is a method, but it gets operator as name, after the operator keyword you specify the operator being overloaded.

An example is worth 1000 words:

struct operatortest string str="" method operator [] takes integer i returns string return SubString(.str,i,i+1) endmethod method operator[]= takes integer i, string ch returns nothing set .str=SubString(.str,0,i)+ch+SubString(.str,i+1,StringLength(.str)-i) endmethod endstruct function test takes nothing returns nothing local operatortest x=operatortest.create() set x.str="Test" call BJDebugMsg( x[1]) call BJDebugMsg( x[0]+x[3]) set x[1] = "." call BJDebugMsg( x.str) endfunction

By this example we are overloading the [] operator and giving it a new function for the objects of type operatortest. The operator [] specifies the replacement for array get and []= is the replacement for array get.

After inspecting the code you may notice that we are making the string function as an array of strings (or actually characters)

The [] operator requires 1 argument (index), the []= operator requires 2 arguments (index and value to assign). [] must return a value.

[] and []= operators can also be declared as static. This might have some uses, the struct name is going to be allowed to use index operators.

There is a lot of criticism towards operator overloading since it allows programmers to make code that does not make sense, please use this feature with responsibility.

You can also overload < and >, notice that there is only syntax to declare < by declaring it you are forcefully determining an order relation for structs of that type. So it automatically makes > based on your < declaration.

struct operatortest string str="" method operator [] takes integer i returns string return SubString(.str,i,i+1) endmethod method operator[]= takes integer i, string ch returns nothing set .str=SubString(.str,0,i)+ch+SubString(.str,i+1,StringLength(.str)-i) endmethod method operator< takes operatortest b returns boolean return StringLength(this.str) < StringLength(b.str) endmethod endstruct function test takes nothing returns nothing local operatortest x=operatortest.create() local operatortest y=operatortest.create() set x.str="Test..." set y.str=".Test" if (x<y) then call BJDebugMsg("Less than") endif if (x>y) then call BJDebugMsg("Greater than") endif endfunction

In the example, an object of type operatortest is considered greater than another object of that type if the length of its str member is greater than the length of the other object's str member.

operator< must return a boolean value and take an argument of the same type as the struct.

Operators are interface friendly meaning that an interface may declare operators, there is a catch and it is that the operator< must be declared without signature in an interface. Also when using > or < to compare interface objects both instances must have the same type, otherwise the function would halt before performing the comparisson, if debug mode was enabled when compiling, it will also show a warning message.

interface ordered method operator < endinterface interface indexed method operator [] takes integer index returns ordered method operator []= takes integer index, ordered v returns nothing endinterface function sort takes indexed a, integer from, integer to returns nothing local integer i local integer j local ordered aux set i=from loop exitwhen (i>=to) set j=i+1 loop exitwhen (j>to) if (a[j]<a[i]) then set aux = a[i] set a[i] = a[j] set a[j] = aux endif set j=j+1 endloop set i=i+1 endloop endfunction

This is an interface for a sorting algorithm. We may now declare custom types that work to sort stuff:

truct integerpair extends ordered integer x integer y method operator< takes integerpair b returns boolean if (b.x==this.x) then return (this.y<b.y) endif return (this.x<b.x) endmethod endstruct type ipairarray extends integerpair array [400] struct integerpairarray extends indexed ipairarray data method operator[] takes integer index returns ordered return ordered( this.data[index] ) endmethod method operator[]= takes integer index, ordered value returns nothing set this.data[index] = integerpair( value) endmethod endstruct

Of course, it is just an example, the logical way would be using quicksort, operators are also good since they would also allow textmacros to use them, the same sorting textmacro might then be compatible with integer, real and any struct with overloaded < operator.

You may also declare a custom ==, works same as < if you declare this operator, != will be translated to not(your method). Also, notice that to do pointer comparisons you will need to use integer(var1)==integer(var2)

More things we can do with custom operators

One thing is to overload [], >, <, you can also make a method mimic a field, to keep abstraction and simplify syntax.

struct X integer a=2 integer b=2 method operator x takes nothing returns integer return this.a*this.b endmethod method operator x= takes integer v returns nothing set this.a=v/this.b endmethod endstruct function test takes nothing returns nothing local X obj= X.create() set obj.x= obj.x + 4 call BJDebugMsg(I2S( obj.x) ) //outputs 8 set obj.b=4 call BJDebugMsg(I2S( obj.x) ) //outputs 16 endfunction

You can use this to implement read only fields:

struct X private integer va=2 method operator a takes nothing returns integer return this.a endmethod endstruct function test takes nothing returns nothing local X obj= X.create() call BJDebugMsg(I2S( obj.a) ) //This is legal set obj.a=2 //this is not endfunction

More importantly, you can use it to implement fields that take extra provisions for assigments:

struct movableEffect private unit dummy private string rfx private effect uniteffect //... //(A lot of code implementing other actions and creation) //... method operator x takes nothing returns real return GetUnitX(this.dummy) endmethod method operator y takes nothing returns real return GetUnitY(this.dummy) endmethod method operator x= takes real value returns nothing call SetUnitX(this.dummy, value) endmethod method operator y= takes real value returns nothing call SetUnitY(this.dummy, value) endmethod method operator effectpath takes nothing returns string return this.rfx endmethod method operator effectpath= takes string path returns nothing set this.rfx=path call DestroyEffect( this.uniteffect) set this.uniteffect = AddSpecialEffectTarget(this.dummy, path, "origin") endmethod endstruct function moveRandom takes movableEffect me returns nothing set me.x= me.x + GetRandomReal(-50,50) set me.y= me.y + GetRandomReal(-50,50) endfunction function toFire takes movableEffect me returns nothing set me.effectpath ="war3mapimporte\\cutefireeffect.mdl" endfunction
Last modified: 16 October 2024