Gah - a solution with more questions. – EntropicLqd
Function call specifiers
From Unreal Wiki, The Unreal Engine Documentation Site
UnrealScript provides two special keywords for calling functions that would otherwise not be accessible: Super for calling overridden functions and Global for calling non-state functions. However, these function call specifiers are only allowed for calling functions on the same instance (or class for static functions) as the code calling the functions.
Contents |
Super
The keyword Super is used to call an overridden version of a function on the same instance or class.
Simple version: Direct parent state or class
Syntax:
Super.functionname([parameters])
The simple version uses the parent context of the current state or class to call the function with the specified name. The parent context of a state is either the parent state or, if the state doesn't extend any other state, the state's containing class. The parent context of a class is its parent class.
Note: If the current context doesn't actually override the function called through Super this call will almost be the same as calling the function directly.
Advanced version: Indirect parent class
Syntax:
Super(classname).functionname([parameters])
The advanced version looks for a class with the specified name. If the call originated in state code or a state function, it looks for a state with the same name in that class and uses that as context for calling the function. If no such state is found, the class is used as context.
Note: This behavior does not play nice with states extending another state with a different name. See examples below.
Global
The keyword Global is used to call the most-derived non-state version of a function. If the instance is not in any state, this has the same effect as calling that function directly.
Syntax:
Global.functionname([parameters])
Examples
For this example we'll use two classes. The parent class A:
class A extends Actor;
function F(); // doesn't override anything
state X
{
function F(); // overrides A.F
}
...and the derived class B:
class B extends A;
function F(); // overrides A.F
state X // extends A.X
{
function F(); // overrides A.X.F
}
state Y extends X
{
function F(); // overrrides B.X.F
}
Now we have an instance of class B that wants to call various implementations of function F():
F();
Global.F();
Super.F();
Super(A).F();
Which implementation those four lines will actually call depends on where exactly they are in class B.
Case 1: No state
If the instance of B is not in any state, the following implementations are called:
- B.F()
- B.F()
- A.F()
- A.F()
No surprises here.
Case 2: State X
If our B instance is in state X, the following implementations are called:
- B.X.F()
- B.F()
- A.X.F()
- A.X.F()
Just as expected.
Case 3: State Y
If the B instance happens to be in state Y, things look a bit different:
- B.Y.F()
- B.F()
- B.X.F()
- A.F()
Wait, Super(A).F() calls the non-state version of F() in class A? Unfortunately this is a limitation of the advanced version of the Super keyword. It doesn't actually check state inheritance, but only looks for a state with the same name in the specified class.
Case 4: Code in state X after switch to state Y
This one is a bit tricky and something you have to watch out for, because it may cause you some trouble. Pretend we have the following function in state B.X:
function G()
{
GotoState('Y');
F();
Global.F();
Super.F();
Super(A).F();
}
The code being executed may still be in state X, but the instance has already switched to state Y. Which versions of F() will be called?
- B.Y.F()
- B.F()
- A.X.F()
- A.X.F()
The second one was expected, Global doesn't care about the state and just calls the global version. Numbers 3 and 4 were kind of expected as well, the code is in state X, so Super calls would be relative to that.
The first one is a bit surprising, though. Code in one state calls a function in a different state! Similar things would happen if you switch from the global state to X or Y or from X or Y to the global state, a simple call to F() will call the new state's implementation.
Be very careful when calling functions after a state switch, the compiler doesn't check for this case. If you try to call a function that is available in the old state, but not in the new state, the game will crash mercilessly!
| Declarations | Classes • Interfaces • Variables • Enums • Structs • Constants • Functions • Operators • Delegates • States • Defaultproperties • Subobjects |
|---|---|
| Types | bool • byte • float • int • name • string • Object • Enums • Structs • Static arrays • Dynamic arrays • Delegates |
| Literals | Boolean • Float • Integer • Names • Objects • Vectors • Rotators • Strings |
| Flow control | Break statement • Continue statement • Do loop • For loop • ForEach loop • GoTo statement • If statement • Return statement • Stop statement • Switch statement • While loop |
