|
|
|
|
|
CfgScript Calling Interface
|
|
|
| ClassDeclaration | Class Methods | Class Members | Calling Interface |
CfgScript support a richt calling interface.
All CfgScript methods are virtual/non-final - except of static methods and constructors.
Call with in/out/inout parameters
CfgScript - and ACDK - supports in, out and inout parameter attributes
-
in is the default attribute (if no other is given).
Values/reference will be passed from caller to callee. Callee may change
value (of basic types) or reference (of object types), but callers
variable will not be changed.
-
out the caller provides an (unitilized) variable
the callee can overwrite the value and pass it back to the caller.
out parameters can act as additional return values.
-
inout is a combination of in and out parameters.
Sample:
class AClass
{
static int foo(in String inS, inout String inoutS, out String erg)
{
erg = inS + inoutS;
inoutS = inS;
inS = "X";
return erg.length();
}
}
String inS = "A";
String inoutS = new String("B");
String outS;
int erg = AClass.foo(inS, inoutS, outS);
out.println("inS: " + inS + "; inoutS: " + inoutS + "; outS: " + outS);
if (inS.equals("A") && inoutS.equals("A") && outS.equals("AB"))
out.println("TEST OK");
else
out.println("TEST FAILED");
|
class MyClass
{
MyClass(int param = 42) { /* ... */ }
}
MyClass cls1 = new MyClass(); // uses 42 for param
MyClass cls2 = new MyClass(1); //
|
Named parameter are useful if a method has many
parameter with default parameters.
class MyRect
{
static void posRect(int xpos = 0, int ypos = 0, int xsize = 20, int ysize = 30)
{
out.println("foo called with xpos = " + xpos + ", ypos = " + ypos + ", xsize = " + xsize + ", ysize = " + ysize);
}
}
// call foo with default
MyRect.posRect();
// call with positional parameter using the default size
MyRect.posRect(10, 10);
// call with positional parameter using the default size
MyRect.posRect(10, 10, 12, 14);
// new syntax
// use default xpos and ypos
MyRect.posRect(xsize: 40, ysize: 50);
// old deprecated syntax
MyRect.posRect(:ypos = 10, :xpos = 50);
|
Limits of default parameters:
- default paramter must not have attribute
out or inout
// Any accepts any type, basic or object type
static void callAny(Any any)
{
if (any instanceof float)
out.println("called any with float: " + any.toString());
else
out.println("called any with " + any.getClass().getName() + ": " + any.toString());
}
MyClass.callAny("asdf");
MyClass.callAny(42.4);
|
This prints:
Called any with acdk/lang/String: asdf
Called any with floating: 42.400002
If the type of last parameter of a method is DmiObjectArray
methods can accept variable count of parameters.
This is similar to void foo(int i, ...); notation
in C/C++.
class MyClass
{
static void variableArgsFunc(int flags, Rest rest)
{
out.println("Function called with " + String.valueOf(rest.length()) + " rest parameters");
foreach (v in rest)
{
out.println(" " + v.getClass().toString() + ": " + v.toString());
}
}
}
// call foo with default
MyClass.variableArgsFunc(42);
MyClass.variableArgsFunc(42, 1, "asdf", new File("testFile"));
|
Limits of rest parameters:
- the paramters before the rest parameter must not bedefault parameter
The type Rest is a typealias to acdk.lang.dmi.DmiObjectArray .
class MyClass
{
static void variableArgsFunc(int flags, NamedRest rest)
{
out.println("Function called with " + String.valueOf(rest.length()) + " rest parameters");
foreach (v in rest)
{
out.println(" " + v.name + ": " + v.value);
}
// convert rest into props to easy access
Props restp = new Props(rest);
if (restp.hasValue("intParam") == true)
{
int i = intParam; // named rest paramater directly available, as they would
// be declared in the method signature
i = restp.intParam; // alternative access as 'pseudo' member variable
out.println(" Has intParam: " + i);
}
else
out.println(" Has No intParam");
}
}
MyClass.variableArgsFunc(42, intParam: 1, stringParam: "asdf", fileParam: new File("testFile"));
MyClass.variableArgsFunc(42);
|
Limits of rest parameters:
- the parameters before the rest named parameter must not bedefault parameter
- the parameters before the rest named parameter must not be called by name
Please refer to Delegates for more Information.
CfgScript supports Multimethods or double dispatch in method calls:
class MyClass
{
void foo(String s) { out.println("called MyClass.foo(String)"); }
void foo(Object s) { out.println("called MyClass.foo(Object)"); }
}
class MyDerivedClass
{
void foo(String s) { out.println("called MyDerivedClass.foo(String)"); }
void foo(Object s) { out.println("called MyDerivedClass.foo(Object)"); }
}
MyClass c = new MyDerivedClass();
Object o = new String("asdf");
c.foo(o);
|
In static typed languages this little code example will print called MyDerivedClass.foo(Object) .
Dispatching only works for the this parameter, but not for the argument.
In CfgScript the output will be called MyDerivedClass.foo(String) , the call will be dispatched regarding
this and the method argument argument.
In CfgScript method calls are not necessarily bound to a specific objects class type.
Some objects are only proxy objects, which represents classes from other
object domains. In some cases the there is no specific type information
for these objects avaible - they are weak types.
Nevertheless it is possible to call methods and access member types of these
objects:
// create a COM Object, like Microsoft Word
Any word = new acdkx.com.ComObject("Word.Application");
// There is no detail metainfo available for this word object
// but we can access members and call methods for this weak object
// type:
word.Visible = 1;
Any doc = word.Documents.add();
Any sel = word.ActiveWindow.Selection;
sel.TypeText("This is ");
sel.Font.Bold = 1;
sel.TypeText("ACDK");
sel.Font.Bold = 0;
sel.TypeText(" instrumenting Word through acdk_cfgscript");
// this a normal ACDK call
acdk.lang.Thread.sleep(3000);
word.Quit(0);
|
|
|