1. Monkey C: How to simulate abstract static methods? - Connect IQ App Development Discussion - Connect IQ - Garmin Forums
   URL: https://forums.garmin.com/developer/connect-iq/f/discussion/410404/monkey-c-how-to-simulate-abstract-static-methods/1928555
   Monkey C: How to simulate abstract static methods? - Connect IQ App Development Discussion - Connect IQ - Garmin Forums

- State Not Answered
- Replies 12 replies
- Subscribers 19 subscribers
- Views 2367 views
- Users 0 members are here

Options

Related

# Monkey C: How to simulate abstract static methods?

A question for the Monkey C experts out there:

I'm looking for some advice on handling a design pattern issue in Monkey C.

Even though Monkey C doesn’t officially support abstract classes, I like to simulate them by defining "abstract" methods that simply throw an exception. This is especially handy when a method is supposed to return an object, and I don't want to create a dummy return value. With this approach, I can safely have code in the abstract class that calls the method, while ensuring that each subclass implements it properly.

This strategy works fine for instance methods. However, I’m running into problems with static methods.

Here's the situation:

I have a static function`A.doMore()` in an abstract-like class`A`.

Inside`doMore()`, I want to call an abstract static method`A.doSomething()`, which would actually be implemented in each subclass, like`B.doSomething()`.

So when I call`B.doMore()`, it should internally call`B.doSomething()`- not`A.doSomething()`.

But when I try this:

Simply calling`doSomething()` inside`A.doMore()` just calls`A.doSomething()`.

Using`self.doSomething()` doesn't solve it either.

And I can’t hard-code`B.doSomething()` in`A`, because I want it to work generically across multiple subclasses.

Is this just a limitation of Monkey C’s type system and static method handling, or is there some workaround I'm missing?

Thanks for any insight you can share!

Below is some sample code illustrating the issue:

```
class A {    public static function doSomething() as Void {        throw new AbstractMethodException( "A.doSomething" );    }     public static function doMore() as Void { // !! This is the issue !!        doSomething();    }}class B extends A {    public static function doSomething() as Void {        // this is what should get done    } }class C {    public function doItAll() as Void {        B.doMore();    }}
```

- Sign in to reply
- Cancel

Is this just a limitation of Monkey C’s type system and static method handling, or is there some workaround I'm missing?

This is how C++, Java, and C# work (where static methods are resolved *statically* - at compile time, not run time), so I'd say it's by design. Whether it's considered a "limitation" might be in the eye of the beholder.

(I realize that what you're asking for is possible in js and python tho.)

Simply calling`doSomething()` inside`A.doMore()` just calls`A.doSomething()`.

Using`self.doSomething()` doesn't solve it either.

For me, if I write code similar to your example and call doSomething() or self.doSomething() in A.doMore(), I get a symbol not found error at run time (although the type checker is happy, even at the strictest level).

Not sure why we're seeing different behaviour, unless your actual implementation of class C also has a function doSomething(), and it's actually C.doSomething() which is being called.

I would consider the type checker thing a bug tho.

As for the implementation details/reasons behind this, if create an instance of C and call C.doItall(), and you print out the value of `self` (or `this`) in C.doItAll() and A.doMore(), you'll find that it has the same value in both cases (meaning it points to the instance of C in both cases).

If you call A.doMore() from outside of a class instance (like a global function), you will find that trying to print the value of self causes a crash, with a "symbol not found" error.

In other words, `self` only has meaning in the context of a non-static class method, so there's no way for A.doMore() to know that it was invoked as B.doMore().

As for workarounds, you could change your static functions so that they take a "classDef" as an arg (this goes back to the other discussion about whether it's possible to do this "correctly" in the type system, regardless of the fact the Method.initialize() does it.

Whenever you call a static function, you would pass the class itself as the first arg:

```
import Toybox.Lang;
import Toybox.System;

class A {
    public static function doSomething() as Void {
        System.println("A");
    }
    public static function doMore(staticClass as A) as Void {
        // yes it's bad to type "staticClass" as A, because if
        // A or B is passed in, as intended, the type checker would
        // allow `staticClass.someInstanceMethodOrVariable` to be accessed,
        // which would cause a crash at runtime
        //
        // don't blame me, blame the type checker / language design
        staticClass.doSomething();
    }
    private static function getClass() as A {
        return A;
    }
}

class B extends A {
    function initialize() {
        A.initialize();
    }
    public static function doSomething() as Void {
        System.println("B");
    }
}

class C {
    public function doItAll() as Void {
        B.doMore(B);
    }
}

function test() as Void {
    new C().doItAll(); // prints "B"
}
```

Specifically, the problem is the type system seemingly doesn't really distinguish between the name of a class (or "classdef") and an instance of said class, for the purpose of variable / arg types.

Not sure why we're seeing different behaviour, unless your actual implementation of class C also has a function doSomething(), and it's actually C.doSomething() which is being called.

As for the implementation details/reasons behind this, if create an instance of C and call C.doItall(), and you print out the value of `self` (or `this`) in C.doItAll() and A.doMore(), you'll find that it has the same value in both cases (meaning it points to the instance of C in both cases).

To illustrate what I'm talking about:

```
import Toybox.Lang;
import Toybox.System;

class A {
    public static function doSomething() as Void {
        System.println("A");
    }
    public static function doMore() as Void {
        // when called from instance of C, calls C.doSomething().
        // when called from global scope or some instance which doesn't
        // have doSomething, crashes with "symbol not found error"
        doSomething(); // [*] line 12
    }
    private static function getClass() as A {
        return A;
    }
}

class B extends A {
    function initialize() {
        A.initialize();
    }
    public static function doSomething() as Void {
        System.println("B");
    }
}

class C {
    public function doItAll() as Void {
        B.doMore();
    }
    public function doSomething() as Void {
        System.println("C");
    }
}

function test() as Void {
    new C().doItAll(); // prints "C" :/
    B.doMore(); // crash at line 12 [*]: "symbol not found error"
}
```

I don't claim that it's good design that a static function in A can somehow call a function in an instance of C, when an instance of C called A's static function in the first place - even the typechecker agrees with me, as it thinks A.doSomething() is actually being called.

I opened a couple of bug reports for this:

Type checker allows static method to be called without qualifier from other static method in same class, but this fails at runtime with a "symbol not found error"

if instance method of one class calls static method of another class, the 2nd class can inadvertently call instance methods on the 1st class

Thanks for diving into this issue again!

I modified by code for the to take the classdef, but when I call the static method from the classdef (line 15 in your example), I get an "Error: Not Enough Arguments Error". I am running it with SDK 8.1.1.

In my admittedly not-so-great example, only doMore() takes the classdef as an arg, not doSomething(). The example as written should compile and run tho.

If you changed *all* static functions to take the classdef (which would be more consistent), then you would call doSomething() as follows:

staticClass.doSomething(staticClass);

Not sure if this workaround is a good idea tho.

Why do you need methods that are both static and abstract? As mentioned, this is not possible even in java. If you already have an object (i.e you have at least 1 non static method in the class) then maybe it's not that big of an overhead to turn the static method into non-static. Wouldn't that solve all the problems?

In my admittedly not-so-great example, only doMore() takes the classdef as an arg, not doSomething(). The example as written should compile and run tho.

OK, I need to do some more testing to understand why this isn't working for me.

Why do you need methods that are both static and abstract? As mentioned, this is not possible even in java. If you already have an object (i.e you have at least 1 non static method in the class) then maybe it's not that big of an overhead to turn the static method into non-static. Wouldn't that solve all the problems?

I have static logic in an abstract class that is shared across all derived classes. However, it also needs to incorporate static behavior that differs depending on which derived class is calling the abstract class's static logic.

behavior that differs depending on which derived class is calling

If it depends on the caller then you'll anyway need to send the caller. Or just use the somewhat strange behaviour of Monkey C that if I understood from this thread and the 2 bug reports kind of does exactly that.

But I'll ask this again:

1. what is the reason to use static methods?

2. am I right in my assumption that if you decided to not use static methods then you wouldn't have these problems? Or maybe I am still missing something.

If it depends on the caller then you'll anyway need to send the caller. Or just use the somewhat strange behaviour of Monkey C that if I understood from this thread and the 2 bug reports kind of does exactly that.

No, the bug/quirk in Monkey C is that if an instance method of a class X calls a static method of class Y (which is unrelated to X), then the "self" reference will point to X, meaning that any unqualified function calls in Y's static method can actually resolve to an instance method in X. This is not what the-ninth wants (or what any reasonable dev could possibly want).

What the-ninth wants is:

- given: class B that extends A

- given: that a static method on B calls a static method on A, and A's static method calls another static method (call it M) which is defined on both A and B (in this case, it's called without using a qualifier, only using the name of the function - i.e. "M()")

- then: M is resolved on B, not A

This won't work for several reasons:

1) In general, M can't be called without a qualifier. e.g. "M()" won't work, only "A.M()" or "B.M()". So a plain call to "M()" wouldn't be resolved to *either* A.M() or B.M().

2) In the quirky case that "M()" could "work", it wouldn't be calling a *static* method on A or B, it would be calling an *instance* method on some other unrelated class

The reason for 1) is that calling "M()" without a qualifier would only work if the self reference is set to either A or B. Even though the type checker believes that calling "M()" from another static method in A would cause it to be resolved to "A.M()", this not the case at runtime. (Surely there's room for improvement here for the compiler to resolve such a call at compile-time to "A.M()", but it still wouldn't achieve what the-ninth wants)

The reason for 2) is the quirk which incorrectly retains the self pointer when an instance method of an class calls a static method of another unrelated class.

EDIT: the one edge case that might fulfill the desired use case:

- an *instance method* of B calls a static method in A, which calls a unqualified function which exists as a static method on both A and B

While this would work, it requires an instance of B which defeats the whole purpose of having static methods in the first place

2. Invoke a c++ class method without a class instance?
   URL: https://stackoverflow.com/questions/10442404/invoke-a-c-class-method-without-a-class-instance
   # Invoke a c++ class method without a class instance?

Tags: c++

- Score: 46
- Views: 101106
- Answers: 7
- Answered: yes
- Asked by: user58925 (563 rep)
- Asked: 2012-05-04
- Site: stackoverflow

## Question

Is it possible to invoke a c++ class method without first creating a class instance?

Suppose we have the following code:

// just an example
#include <iostream>
using namespace std;

class MyClass {
 public:
 MyClass();
 ~MyClass();
 int MyMethod(int *a, int *b);
};

// just a dummy method
int MyClass::MyMethod(int *a, int *b){;
 return a[0] - b[0];
}

Here's another example:

#include <iostream>
using namespace std;

class MyClassAnother {
 public:
 MyClassAnother();
 ~MyClassAnother();
 int MyMethod(int *a, int *b);
};

// just a dummy method
int MyClassAnother::MyMethod(int *a, int *b){;
 return a[0] + b[0];
}

As we can see, in the above examples, both classes have no internal variables and use dummy constructors / destructors; Their sole purpose is to expose one public method, MyMethod(..). Here's my question: assume there are 100 such classes in the file (all with different class names, but with an identical structure -- one public method having the same prototype -- MyMethod(..).

Is there a way to invoke the MyMethod(..) method calls of each one of the classes without first creating a class instance for each?

## Answers

### Answer by Greyson (score: 72 [ACCEPTED])

Use the keyword 'static' to declare the method:

static int MyMethod( int * a, int * b );

Then you can call the method without an instance like so:

int one = 1;
int two = 2;

MyClass::MyMethod( &two, &one );

'static' methods are functions which only use the class as a namespace, and do not require an instance.

### Answer by Mark Ransom (score: 6)

You can call a class method without an instance by declaring it static, but that doesn't appear to be what you want. You want to be able to call the same method on 100 different classes.

There are two ways for C++ to differentiate between different class methods. One is to do it at compile time, and one is to do it at run time. At compile time you need to invoke the class name itself as part of the call on a static method, or you need the object instance or pointer to be to a specific derived class. At run time you can call a method polymorphically if you have declared the method virtual. Note that you need an object of the class to use either of the run-time methods.

### Answer by Patrick vD (score: 3)

I don't know why no one else mentioned this, but from the functionality described in your comments, it sounds like what you want is a namespace, not a class. It's perfectly fine for you to have 100 functions with the same name defined in 100 differently named namespaces. It should behave exactly as you are describing, and is the entire purpose behind namespaces.

### Answer by stanigator (score: 0)

As Mark Random and Greyson mentioned, you can make that method static, and then invoke the right signature without instantiating an object. However, you may want to think twice about writing your function this way rather than writing a different version of that same function. Here are the considerations, especially for a large program:

static methods are difficult to write unit tests for.
B/c of the nature of static methods, they reside in the memory all the time.
Multithreading would be difficult if your program needs to utilize it.

### Answer by Ryan Haining (score: 0)

If you want to group functions together under a named scope, then you'd be better off with a namespace. You can access functions of a namespace with the scope resolution operator ::
namespace my_namespace {
 int my_function(int *a, int *b) {
 return a[0] + b[0];
 }
}

int main() {
 int* arr1 = /* ... */
 int* arr2 = /* ... */
 my_namespace::my_function(arr1, arr2);
}

### Answer by GorishBombish (score: -1)

Yeap. You definitely shouldn't do this in production code, but in this case you can call class method using empty pointer and it will work. Technically you don't create a class instance.
#include <iostream>
using namespace std;

class MyClass {
 public:
 MyClass();
 ~MyClass();
 int MyMethod(int *a, int *b);
};

// just a dummy method
int MyClass::MyMethod(int *a, int *b){;
 return a[0] - b[0];
}

int main() {
 MyClass *myClass = nullptr;
 int a = 1;
 int b = 2;
 std::cout << res = myClass->MyMethod(&a, &b) << std::endl;
}

Wubba Lubba dub-dub!

### Answer by Aaron B. (score: -1)

Yes, you can call a function of an uninstantiated object--but don't expect to be able to refer to any of the objects members (they don't exist).
IDK why it works. Its definitely got some bad code smell. Agreed that static functions is better, but this is still interesting.
#include <memory>
#include <iostream>

class foo
{
public:
 void print() {std::cout<<"Hello World" <<std::endl;}
 int m_val;
};

int main ()
{
 std::shared_ptr<foo> p1;
 p1->print();
 return 0;
}

3. Monkey Documentation
   URL: https://regal-internet-brothers.github.io/monkey/docs/Programming_Keywords_Method.html
   Monkey Documentation

# Keyword Method

Declares the beginning of a class method.

## Syntax

Method Identifier: ReturnType ( Parameters ) [ Property ] [ Abstract ] [ Final ]~n Statements... End [ Method ]

## Description

The Method keyword begins the declaration of a class method.

Please see the Methods section of the monkey language reference for more information on methods.

## See also

## Examples

An example of methods as statements.

`Class``GameObject``Field``x``:``Float``Field``y``:``Float``Method``PrintX`` ()``Print``x``End``Method``PrintY`` ()``Print``y``End``End``Local``g``:``GameObject`` = ``New``GameObject``p.x`` = ``100``p.y`` = ``200``' Accessing method...``p.PrintX``p.PrintY`

Strict mode version of above GameObject class. (Note use of Void return type.)

`Class``GameObject``Field``x``:``Float``Field``y``:``Float``Method``PrintX``:``Void`` ()``Print``x``End``Method``PrintY``:``Void`` ()``Print``y``End``End`

Method returning value of Float type.

`Class``GameObject``Method``AddFloats``:``Float`` (``value1``:``Float``, ``value2``:``Float``)``Return``value1`` + ``value2``End``End``Local``g``:``GameObject`` = ``New``GameObject``' Accessing method...``Print``g.AddFloats`` (``1.5``, ``2.0``)`

4. Reflection is in! – Monkey 2
   URL: https://www.monkeycoder.co.nz/2016/10/23/reflection-is-in/
   Reflection is in! – Monkey 2

Hi,

Ok, it’s still a bit WIP, but the core of the reflection system is now in!

It introduces 3 new ‘builtin’ types:

- Tutorials
- Variant – a ‘boxing’ type that lets you set/get/invoke variables etc in a uniform way.
- TypeInfo – that lets you inspect the names, kinds and decls of a type at runtime.
- DeclInfo – that lets you modify variables and invoke methods/functions.

I’ve added a simple reflecttest banana too.

### Variants

The ‘Variant’ type is a primitive type that can be used to ‘box’ values of any type.

The easiest way to create a variant is to cast a value to Variant (much like casting an Int to String etc), eg:

Monkey

Local v:=Variant( 10 )

1

2

Local v:=Variant( 10 )

An uninitialized variant will contain a ‘null’ value (of type Void) until you assign something to it:

Monkey

Local v:Variant v=10 'variant now contains an int 10. v="hello" 'variant now contains a string "hello".

1

2

3

4

Local v:Variant

v=10 'variant now contains an int 10.

v="hello" 'variant now contains a string "hello".

A variant is ‘true’ if it contains any value with a non-void type (including a bool false value!) and ‘false’ if it is uninitialized and has no (void) type.

Any type of value can be implicitly converted to a variant, so you can easily pass anything to a function with variant parameters:

Monkey

Function Test( v:Variant ) End Function Main() Test( 1 ) Test( "Hello" ) Test( New Int[] ) Test( Main ) End

1

2

3

4

5

6

7

8

9

Function Test( v:Variant )

End

Function Main()

Test( 1 )

Test( "Hello" )

Test( New Int[] )

Test( Main )

End

To retrieve the value contained in a variant, you must explicitly cast the variant to the desired type:

Monkey

Local v:=Variant( 100 ) Print Cast ( v )

1

2

3

Local v:=Variant( 100 )

Print Cast ( v )

Note that the cast must specify the exact type of the value already contained in the variant, or a runtime error will occur:

Monkey

Local v:=Variant( 10 ) Print Cast ( v ) 'Runtime error! Variant contains an Int not a String!

1

2

3

4

Local v:=Variant( 10 )

Print Cast ( v ) 'Runtime error! Variant contains an Int not a String!

The one exception to this is if the Variant contains a class object, in which case you can cast the variant to any valid base class of the object.

### Typeof and TypeInfo

The Typeof operator returns a TypeInfo object that contains various properties and methods for inspecting types at runtime. There are 2 ways to use Typeof:

Monkey

Local type:=Typeof( expression ) Local type:=Typeof< type >

1

2

3

Local type:=Typeof( expression )

Local type:=Typeof< type >

The use of seperate () and <> delimeters is to prevent the parser getting confused by complex expressions/types.

TypeInfo objects have a To:String operator (mainly for debugging) so can be printed directly:

Monkey

Print Typeof Print Typeof Local t:=10 Print Typeof( t ) Print Typeof( "yes" )

1

2

3

4

5

6

Print Typeof

Print Typeof

Local t:=10

Print Typeof( t )

Print Typeof( "yes" )

Typeof returns the ‘static’ type of a class object. To get the actual instance type, use the Object.InstanceType property:

Monkey

Class C End Class D Extends C End Function Main() Local c:C=new D Print Typeof( c ) 'Class default.C Print c.InstanceType 'Class default.D End

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Class C

End

Class D Extends C

End

Function Main()

Local c:C=new D

Print Typeof( c ) 'Class default.C

Print c.InstanceType 'Class default.D

End

You can retrieve the type of the value contained in a variant using the Variant.Type property:

Monkey

Local v:=Variant( 10 ) 'creates a variant containing an int. Print v.Type 'prints 'Int'

1

2

3

4

Local v:=Variant( 10 ) 'creates a variant containing an int.

Print v.Type 'prints 'Int'

TypeInfo also includes functions for inspecting all user defined types:

Monkey

Function TypeInfo.GetType( name:String )

1

Function TypeInfo.GetType( name:String )

Returns the TypeInfo for a named type. A named type is a namespace or class declared by your app – it does not include primitive types, pointer types, array types etc. Class names must be prefixed by the namespace they are declared in.

To get an array of ALL named types:

Monkey

Function TypeInfo.GetTypes:TypeInfo[]()

1

Function TypeInfo.GetTypes:TypeInfo[]()

### DeclInfo objects

TypeInfo objects for namespaces and classes also contain a set of DeclInfo objects. A DeclInfo represents the member declarations inside of a namespace or class. Currently, only global, field, method and function members are supported. DeclInfo objects also have a To:String operator to help with debugging.

You can inspect the member decls of a type using the TypeInfo.GetDecls method:

Monkey

Namespace mynamespace Class C Field x:Int Field y:Int End Function Main() Local type:=TypeInfo.GetType( "mynamespace.MyClass" ) For Local decl:=Eachin type.GetDecls() Print decl Next End

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Namespace mynamespace

Class C

Field x:Int

Field y:Int

End

Function Main()

Local type:=TypeInfo.GetType( "mynamespace.MyClass" )

For Local decl:=Eachin type.GetDecls()

Print decl

Next

End

You can retrieve a single unique member using TypeInfo.GetDecl:

Monkey

Local type:=TypeInfo.GetType( "mynamespace.MyClass" ) Local ctor:=type.GetDecl( "New" )

1

2

3

4

Local type:=TypeInfo.GetType( "mynamespace.MyClass" )

Local ctor:=type.GetDecl( "New" )

There may be several decls with the same name due to method and function overloading, in which case the simple GetDecl above will fail and return null. In this case, you either need to inspect each decl individually to find the one you want, or you can pass an additional TypeInfo parameter to GetDecl:

Monkey

Local type:=TypeInfo.GetType( "MyNamespace.MyClass" ) Local ctor:=type.GetDecl( "New",Typeof<Void()> )

1

2

3

4

Local type:=TypeInfo.GetType( "MyNamespace.MyClass" )

Local ctor:=type.GetDecl( "New",Typeof<Void()> )

This will return the default constructor for MyClass, assuming there is one.

### Getting and setting variables

Member decls that represent variables (ie: fields and globals) can be read and written using the DeclInfo.Get and Decl.Info.Set methods:

Monkey

Namespace mynamespace Global MyGlobal:Int Function Main() Local vdecl:=TypeInfo.GetType( "mynamespace" ).GetDecl( "MyGlobal" ) vdecl.Set( Null,10 ) Print MyGlobal Print Cast ( vdecl.Get( Null ) ) End

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Namespace mynamespace

Global MyGlobal:Int

Function Main()

Local vdecl:=TypeInfo.GetType( "mynamespace" ).GetDecl( "MyGlobal" )

vdecl.Set( Null,10 )

Print MyGlobal

Print Cast ( vdecl.Get( Null ) )

End

The first parameter of Set and Get is an object instance, which must be non-null for getting and setting fields.

The second parameter of Set is a variant, and is the value to assign to the variable. The type of the value contained in the variant must match the variable type exactly, or a runtime error will occur.

Note that since any value can be cast to a variant, we can just provide the literal value ’10’ for Set and it will be implictly converted to a variant for us. On the other hand, we must explicitly cast the result of Get() from a variant back to the type of value we want.

### Invoking methods and functions

To invoke methods and functions, use the DeclInfo.Invoke method:

Monkey

namespace mynamespace Function Test( msg:String ) Print "Test! msg="+msg End Function Main() Local fdecl:=TypeInfo.GetType( "mynamespace" ).GetDecl( "Test" ) fdecl.Invoke( Null,New Variant[]( "Hello Test!" ) ) End

1

2

3

4

5

6

7

8

9

10

11

12

13

14

namespace mynamespace

Function Test( msg:String )

Print "Test! msg="+msg

End

Function Main()

Local fdecl:=TypeInfo.GetType( "mynamespace" ).GetDecl( "Test" )

fdecl.Invoke( Null,New Variant[]( "Hello Test!" ) )

End

The first parameter of Invoke is an object instance, which must be non-null for invoking methods.

The second parameter of Invoke is an array of variants that represents the parameters for the call. The types of these parameters must match the parameter types of the actual method or function exactly, or a runtime error will occur.

### Limitations

Currently, typeinfo is only generated for non-generic, non-extension, non-extern 100% pure monkey2 globals, fields, function, methods, classes and namespaces. You can still use other types (structs etc) with variants etc, but you wont be able to inspect their members.

Typeinfo may be stripped out by the linker. I’ve added a little hack to mojo to keep module typeinfo ‘alive’, but there is still work to do here. If you find the linker stripping out typeinfo, you can prevent it doing so for now by adding a ‘Typeof’ to Main() referencing the type you want to keep alive. Or, you can set MX2_WHOLE_ARCHIVE in bin/env_blah.txt to ‘1’ to force the linker to include ALL code, but this will of course produce larger executables.

0

5. Monkey Game Programming step by step: Monkey-X - Putting/Calling functions in/from Classes - code example
   URL: http://monkeygameprogramming.blogspot.com/2015/02/monkey-x-puttingcalling-functions.html
   Monkey Game Programming step by step: Monkey-X - Putting/Calling functions in/from Classes - code example

```
This might be useful to keep code organised.
```

```
Code below :
```

```
Import mojo

Class myfuncs
    Function drawvalue(val:Int,x:Int,y:Int)
        DrawText "value is : " + val,x,y
    End Function
    Function drawdistance(x1:Int,y1:Int,x2:Int,y2:Int,x:Int,y:Int)
        Local d:Int=Abs(x2-x1)+Abs(y2-y1)
        DrawText "distance is : "+d,x,y
    End Function
End Class

Class MyGame Extends App

    Method OnCreate()
        SetUpdateRate(60)
    End Method
    Method OnUpdate()
    End Method
    Method OnRender()
        Cls 0,0,0
        SetColor 255,255,255
        myfuncs.drawvalue(10,0,15)
        myfuncs.drawdistance(0,0,10,10,0,30)
    End Method
End Class

Function Main()
    New MyGame()
End Function
```

6. Call an object method - Rosetta Code
   URL: https://rosettacode.org/wiki/Call_an_object_method
   Call an object method - Rosetta Code

In object-oriented programming a method is a function associated with a particular class or object. In most forms of object oriented implementations methods can be static, associated with the class itself; or instance, associated with an instance of a class.

Show how to call a static or class method, and an instance method of a class.

## ActionScript

```
// Static
MyClass.method(someParameter);

// Instance
myInstance.method(someParameter);

```

## Ada

Ada is a language based on strict typing. Nevertheless, since Ada 95 (the first major revision of the language), Ada also includes the concepts of a class. Types may be tagged, and for each tagged type T there is an associated type T'Class. If you define a method as "procedure Primitive(Self: T)", the actual parameter Self must be of type T, exactly, and the method Primitive will be called, well, statically. This may be surprising, if you are used to other object-oriented languages.

If you define a method as "prodedure Dynamic(Self: T'Class)", the actual parameter can be either T or any of its descendents. Now, if you call Self.Primitive within the procedure Dynamic, it will be dispatching, i.e., it will call the primitive function matching the type of Self (i.e., either T or any of its subtype). This is what you would expect in many other object-oriented languages.

Finally, a static method can be defined as a subprogram within the same package that holds the object type and the other methods.

Specify the class My_Class, with one primitive subprogram, one dynamic subprogram and a static subprogram:

```
   package My_Class is
      type Object is tagged private;
      procedure Primitive(Self: Object); -- primitive subprogram
      procedure Dynamic(Self: Object'Class);
      procedure Static;
   private
      type Object is tagged null record;
   end My_Class;

```

Implement the package:

```
   package body My_Class is
      procedure Primitive(Self: Object) is
      begin
	 Put_Line("Hello World!");
      end Primitive;

      procedure Dynamic(Self: Object'Class) is
      begin
	 Put("Hi there! ... ");
	 Self.Primitive; -- dispatching call: calls different subprograms,
                         -- depending on the type of Self
      end Dynamic;

      procedure Static is
      begin
	 Put_Line("Greetings");
      end Static;
   end My_Class;

```

Specify and implement a subclass of My_Class:

```
   package Other_Class is
      type Object is new My_Class.Object with null record;
      overriding procedure Primitive(Self: Object);
   end Other_Class;

   package body Other_Class is
      procedure Primitive(Self: Object) is
      begin
	 Put_Line("Hello Universe!");
      end Primitive;
   end Other_Class;

```

The main program, making the dynamic and static calls:

```
with Ada.Text_IO; use Ada.Text_IO;

procedure Call_Method is

   package My_Class is ... -- see above
   package body My_Class is ... -- see above

   package Other_Class is ... -- see above
   package body Other_Class is ... -- see above

   Ob1: My_Class.Object; -- our "root" type
   Ob2: Other_Class.Object; -- a type derived from the "root" type

begin
   My_Class.Static;
   Ob1.Primitive;
   Ob2.Primitive;
   Ob1.Dynamic;
   Ob2.Dynamic;
end Call_Method;

```

Output:

```
Greetings
Hello World!
Hello Universe!
Hi there! ... Hello World!
Hi there! ... Hello Universe!
```

## ALGOL 68

Algol 68 doesn't do OO as such, but it has structures, the members of which can be procedures. This allows OO features to be implemented, though without syntactic sugar, "this" pointers must be passed explicitly. In Algol 68,`a OF b` is used where most other languages would use`b.a`. This means that a call to an instance method called "print" say of a class instance "a" in Algol 68 would be written`( print OF a )( a )`, - note the explicit "this" parameter - whereas`a.print` would be used in most other languages. Class methods could be members of the structure (as here) without a "this" parameter, or could be procedures defined outside the structure. In this example, the instance and class methods return VOID, but this is not necessary, any return type could be used.

```
BEGIN # demonstrate a possible method of simulating class & instance methods  #
    # declare a "class"                                                       #
    MODE ANIMAL = STRUCT( STRING                 species
                        , PROC( REF ANIMAL )VOID print    # instance method   #
                        , PROC VOID              cm       # class method      #
                        );
    # constructor                                                             #
    PROC new animal = ( STRING species )REF REF ANIMAL:
         BEGIN
             HEAP ANIMAL     newv := ANIMAL( species
                                           , ( REF ANIMAL this )VOID:
                                               print( ( "[animal instance[", species OF this, "]]" ) )
                                           , VOID: print( ( "[animal class method called]" ) )
                                           );
             HEAP REF ANIMAL newa := newv;
             newa
         END # new animal # ;

    REF ANIMAL a
           := new animal( "PANTHERA TIGRIS" ); # create an instance of ANIMAL #
    cm OF a;                                   # call the class method        #
    ( print OF a )( a )                        # call the instance method     #
END
```

Output:

```
[animal class method called][animal instance[PANTHERA TIGRIS]]

```

## Apex

```
// Static
MyClass.method(someParameter);

// Instance
myInstance.method(someParameter);

```

## ArkScript

Works with: ArkScript version 4.0.0

ArkScript does not have objects, but can emulate them using closures. This also means it does not have static method per se.

```
(let create_user (fun (username password age) {
  (let change_username (fun (new_name)
    (set username new_name)))
  (let check_password (fun (pass)
    (= pass password)))

  (fun (&username &password &age &change_username &check_password) ()) }))

(let me (create_user "Lex" "passw0rd" 25))
(let john (create_user "John" "qwerty123" 28))

(assert (not (me.check_password "test!")) "password is not 'test!'")
(assert (!= me.username john.username) "usernames are distinct")

(assert (= me.username "Lex") "my username is Lex")
(me.change_username "Rosetta")
(assert (= me.username "Rosetta") "my username is now Rosetta!")
```

Here we are creating closures using`create_user`, and we can access every captured value with`closure.field`. Fields are read-only, meaning we need to use captured functions to mutate the internal closure state.

## AutoHotkey

(AutoHotkey Basic does not have classes)

```
class myClass
{
	Method(someParameter){
		MsgBox % SomeParameter
	}
}

myClass.method("hi")
myInstance := new myClass
myInstance.Method("bye")

```

## Bracmat

Bracmat has no classes. Rather, objects can be created as copies of other objects. In the example below, the variable`MyObject` has a copy of variable`MyClass` as value. Notice the extra level of reference in`(MyObject..Method)$argument`, comparable to`MyObject->Method(argument)` in C. Rather than being the object itself,`MyObject` points to an object and can be aliased by assigning to another variable.

Inside an object, the object is represented by`its`, comparable to`this` in other languages.

```
( ( myClass
  =   (name=aClass)
      ( Method
      = .out$(str$("Output from " !(its.name) ": " !arg))
      )
      (new=.!arg:?(its.name))
  )
& (myClass.Method)$"Example of calling a 'class' method"
& new$(myClass,object1):?MyObject
& (MyObject..Method)$"Example of calling an instance method"
& !MyObject:?Alias
& (Alias..Method)$"Example of calling an instance method from an alias"
);
```

Output:

```
Output from aClass: Example of calling a 'class' method
Output from object1: Example of calling an instance method
Output from object1: Example of calling an instance method from an alias
```

## BQN

BQN has namespaces which can act as objects if you squint your eyes hard enough. Here's some methods:

```
foo ← {
  Spam ⇐ {𝕊: "Wonderful Spam!!!"}
  Eggs ⇐ {𝕨+𝕩}
}

•Show 1 foo.Eggs 2
      foo.Spam@

```

And here is the output of this code:

```
3
"Wonderful Spam!!!"
```

## C

C has structures and it also has function pointers, which allows C structures to be associated with any function with the same signature as the pointer. Thus, C structures can also have object methods.

```
#include<stdlib.h>
#include<stdio.h>

typedef struct{
        int x;
        int (*funcPtr)(int);
}functionPair;

int factorial(int num){
        if(num==0||num==1)
                return 1;
        else
                return num*factorial(num-1);
}

int main(int argc,char** argv)
{
        functionPair response;

        if(argc!=2)
                return printf("Usage : %s <non negative integer>",argv[0]);
        else{
                response = (functionPair){.x = atoi(argv[1]),.funcPtr=&factorial};
                printf("\nFactorial of %d is %d\n",response.x,response.funcPtr(response.x));
        }
        return 0;
}

```

And yes, it works :

```
$ ./a.out 10

Factorial of 10 is 3628800

```

## C++

```
// Static
MyClass::method(someParameter);

// Instance
myInstance.method(someParameter);

// Pointer
MyPointer->method(someParameter);

```

## C_sharp

```
// Static
MyClass.Method(someParameter);

// Instance
myInstance.Method(someParameter);

```

## ChucK

```
MyClass myClassObject;
myClassObject.myFunction(some parameter);

```

## Clojure

```
(Long/toHexString 15) ; use forward slash for static methods
(System/currentTimeMillis)

(.equals 1 2)    ; use dot operator to call instance methods
(. 1 (equals 2)) ; alternative style

```

## COBOL

Works with: COBOL 2002

There are two ways to invoke a method: the`INVOKE` statement and inline method invocation.

```
*> INVOKE statements.
INVOKE my-class "some-method"          *> Factory object
    USING BY REFERENCE some-parameter
    RETURNING foo
INVOKE my-instance "another-method"    *> Instance object
    USING BY REFERENCE some-parameter
    RETURNING foo

*> Inline method invocation.
MOVE my-class::"some-method"(some-parameter) TO foo       *> Factory object
MOVE my-instance::"another-method"(some-parameter) TO foo *> Instance object

```

To call factory methods of objects of an unknown type (such as when you may have a subclass of the class wanted), it is necessary to get a reference to the class's factory object by calling the`"FactoryObject"` method.

```
INVOKE some-instance "FactoryObject" RETURNING foo-factory
*> foo-factory can be treated like a normal object reference.
INVOKE foo-factory "someMethod"

```

## CoffeeScript

While CoffeeScript does provide a useful class abstraction around its prototype-based inheritance, there aren't any actual classes.

```
class Foo
    @staticMethod: -> 'Bar'

    instanceMethod: -> 'Baz'

foo = new Foo

foo.instanceMethod() #=> 'Baz'
Foo.staticMethod() #=> 'Bar'

```

## Common Lisp

In Common Lisp, classmethods are methods that apply to classes, rather than classes that contain methods.

```
(defclass my-class ()
  ((x
    :accessor get-x  ;; getter function
    :initarg :x      ;; arg name
    :initform 0)))   ;; initial value

;; declaring a public class method
(defmethod square-x ((class-instance my-class))
  (* (get-x class-instance) (get-x class-instance)))

;; create an instance of my-class
(defvar *instance*
  (make-instance 'my-class :x 10))

(format t "Value of x: ~a~%" (get-x *instance*))

(format t "Value of x^2: ~a~%" (square-x *instance*))

```

Output (CLISP v2.49):

```
$ clisp object.cl
Value of x: 10
Value of x^2: 100

```

## D

```
struct Cat {
    static int staticMethod() {
        return 2;
    }

    string dynamicMethod() { // Never virtual.
        return "Mew!";
    }
}

class Dog {
    static int staticMethod() {
        return 5;
    }

    string dynamicMethod() { // Virtual method.
        return "Woof!";
    }
}

void main() {
    // Static methods calls:
    assert(Cat.staticMethod() == 2);
    assert(Dog.staticMethod() == 5);

    Cat c; // This is a value on the stack.
    Dog d; // This is just a reference, set to null.

    // Other static method calls, discouraged:
    assert(c.staticMethod() == 2);
    assert(d.staticMethod() == 5);

    // Instance method calls:
    assert(c.dynamicMethod() == "Mew!");
    d = new Dog;
    assert(d.dynamicMethod() == "Woof!");
}

```

## Delphi

Works with: Delphi version 6.0

This example shows the creation of a simple integer stack object. The object contains "Push" and "Pop" static methods.

```
{Simple stack interface}

type TSimpleStack = class(TObject)
 private
  FStack: array of integer;
 protected
 public
  procedure Push(I: integer);
  function Pop(var I: integer): boolean;
  constructor Create;
 end;

{ TSimpleStack implementation }

constructor TSimpleStack.Create;
{Initialize stack by setting size to zero}
begin
SetLength(FStack,0);
end;

function TSimpleStack.Pop(var I: integer): boolean;
{Pop top item off stack into "I" returns False if stack empty}
begin
Result:=Length(FStack)>=1;
if Result then
	begin
	{Get item from top of stack}
	I:=FStack[High(FStack)];
	{Delete the top item}
	SetLength(FStack,Length(FStack)-1);
	end;
end;

procedure TSimpleStack.Push(I: integer);
{Push item on stack by adding to end of array}
begin
{Increase stack size by one}
SetLength(FStack,Length(FStack)+1);
{Insert item}
FStack[High(FStack)]:=I;
end;

procedure ShowStaticMethodCall(Memo: TMemo);
var Stack: TSimpleStack;	{Declare stack object}
var I: integer;
begin
{Instanciate stack object}
Stack:=TSimpleStack.Create;
{Push items on stack by calling static method "Push"}
for I:=1 to 10 do Stack.Push(I);
{Call static method "Pop" to retrieve and display stack items}
while Stack.Pop(I) do
	begin
	Memo.Lines.Add(IntToStr(I));
	end;
{release stack memory and delete object}
Stack.Free;
end;

```

Output:

```
10
9
8
7
6
5
4
3
2
1
Elapsed Time: 10.571 ms.

```

## Dragon

Making an object of class and then calling it.

```
r = new run()
r.val()
```

## Dyalect

Dyalect supports both instance and static methods. Instance methods have a special`this` reference that returns an instance. Static method are always invoked through the type name.

```
//Static method on a built-in type Integer
static func Integer.Div(x, y) {
    x / y
}

//Instance method
func Integer.Div(n) {
    this / n
}

print(Integer.Div(12, 3))
print(12.Div(3))
```

Output:

```
4
4
```

## E

This example is in need of improvement:

Add runnable example.

A method call in E has the syntax`recipient.verb(arg1, arg2, ...)`, where recipient is an expression, verb is an identifier (or a string literal preceded by`::`), and argN are expressions.

```
someObject.someMethod(someParameter)
```

In E, there are no distinguished "static methods". Instead, it is idiomatic to place methods on the maker of the object. This is very similar to methods on constructors in JavaScript, or class methods in Objective-C.

## Ecstasy

Calling a method or function in Ecstasy follows roughly the same conventions as in Java and C#, but in order to prevent certain types of bugs, Ecstasy explicitly disallows calling a function as if it were a method.

```
module CallMethod {
    /**
     * This is a class with a method and a function.
     */
    const Example(String text) {
        @Override
        String toString() {                             // <-- this is a method
            return $"This is an example with text={text}";
        }

        static Int oneMoreThan(Int n) {                 // <-- this is a function
            return n+1;
        }
    }

    void run() {
        @Inject Console console;

        Example example      = new Example("hello!");
        String  methodResult = example.toString();      // <-- call a method
        console.print($"Result from calling a method: {methodResult.quoted()}");

     // Int funcResult = example.oneMoreThan(12);      // <-- compiler error
        Int funcResult = Example.oneMoreThan(12);      // <-- call a function
        console.print($"Results from calling a function: {funcResult}");

        // methods and functions are also objects that can be manipulated;
        // note that "function String()" === "Function<<>, <String>>"
        Method<Example, <>, <String>> method = Example.toString;
        function String() func   = method.bindTarget(example);
        console.print($"Calling a bound method: {func().quoted()}");

        // by default, a method with target T converts to a function taking a T;
        // Ecstasy refers to this as "Bjarning" (because C++ takes "this" as a param)
        val func2 = Example.toString;                   // <-- type: function String()
        console.print($"Calling a Bjarne'd function: {func2(example).quoted()}");

        // the function is just an object, and invocation (and in this case, binding,
        // as indicated by the '&' operator which requests a reference) is accomplished
        // using the "()" operator
        val func3 = Example.oneMoreThan;                // <-- type: function Int(Int)
        val func4 = &func3(13);                         // <-- type: function Int()
        console.print($"Calling a fully bound function: {func4()}");
    }
}

```

Output:

```
Result from calling a method: "This is an example with text=hello!"
Results from calling a function: 13
Calling a bound method: "This is an example with text=hello!"
Calling a Bjarne'd function: "This is an example with text=hello!"
Calling a fully bound function: 14

```

## Elena

The message call:

```
    Console.printLine("Hello"," ","World!");
```

## Elixir

Elixir doesn't do objects. Instead of calling methods on object you send messages to processes. Here's an example of a process created with spawn_link which knows how to receive a message "concat" and return a result.

```
defmodule ObjectCall do
  def new() do
    spawn_link(fn -> loop end)
  end

  defp loop do
    receive do
      {:concat, {caller, [str1, str2]}} ->
        result = str1 <> str2
        send caller, {:ok, result}
        loop
    end
  end

  def concat(obj, str1, str2) do
    send obj, {:concat, {self(), [str1, str2]}}

    receive do
      {:ok, result} ->
        result
    end
  end
end

obj = ObjectCall.new()

IO.puts(obj |> ObjectCall.concat("Hello ", "World!"))

```

## EMal

Translation of: Wren

```
in Org:RosettaCode
type MyClass ^|we are defining a new data type and entering in its static context|^
fun method ← void by block do writeLine("static method called") end
model ^|we enter the instance context|^
  fun method ← void by block do writeLine("instance method called") end
end
type CallAnObjectMethod
var myInstance ← MyClass() ^|creating an instance|^
myInstance.method()
myInstance["method"]() ^|using symbolic references|^
MyClass.method()
var("Org:RosettaCode:MyClass", "method")() ^|using symbolic references|^
```

Output:

```
instance method called
instance method called
static method called
static method called

```

## F#

```
// Call an object method. Nigel Galloway: April 17th., 2026
type myClass(g:string)=
  let n=g
  static member whoAreUstat n=printfn "A static member of myClass %s" n
  member this.whoAreUins=printfn "An instance member of myClass %s" n

myClass.whoAreUstat "Nigel"
(myClass "Nigel").whoAreUins

```

Output:

```
A static member of myClass Nigel
An instance member of myClass Nigel

```

## Factor

In Factor, there is no distinction between instance and static methods. Methods are contained in generic words and specialize on a class. Generic words define a method combination so methods know which object(s) to dispatch on. (But most methods dispatch on the object at the top of the data stack.) Under this object model, calling a method is no different than calling any other word.

```
USING: accessors io kernel literals math sequences ;
IN: rosetta-code.call-a-method

! Define some classes.
SINGLETON: dog
TUPLE: cat sassiness ;

! Define a constructor for cat.
C: <cat> cat

! Define a generic word that dispatches on the object at the top
! of the data stack.
GENERIC: speak ( obj -- )

! Define methods in speak which specialize on various classes.
M: dog speak drop "Woof!" print ;
M: cat speak sassiness>> 0.5 > "Hiss!" "Meow!" ? print ;
M: object speak drop "I don't know how to speak!" print ;

! Call speak on various objects.
! Despite being a method, it's called like any other word.
dog speak
0.75 <cat> speak
0.1 <cat> speak
"bird" speak

```

Output:

```
Woof!
Hiss!
Meow!
I don't know how to speak!

```

## Forth

Works with: 4tH version 3.62.0

Translation of: D

There are numerous, mutually incompatible object oriented frameworks for Forth. This one works with the FOOS preprocessor extension of 4tH.

```
include lib/compare.4th
include 4pp/lib/foos.4pp

[ASSERT]                               \ enable assertions

:: Cat
   class
     method: dynamicCat                \ virtual method
   end-class {

    :static staticCat { 2 } ;          \ static method
    :method { s" Mew!" } ; defines dynamicCat
  }                                    \ for unrelated classes,
;                                      \ method names have to differ

:: Dog
   class
     method: dynamicDog                \ virtual method
   end-class {

    :static staticDog { 5 } ;
    :method { s" Woof!" } ; defines dynamicDog
  }                                    \ for unrelated classes,
;                                      \ method names have to differ

static Cat c                           \ create two static objects
static Dog d

: main
  assert( class -> staticCat 2 = )     \ check for valid method return
  assert( class -> staticDog 5 = )     \ of a static method

  assert( c -> staticCat 2 = )         \ check for valid method return
  assert( d -> staticDog 5 = )         \ of a static method

  assert( c => dynamicCat s" Mew!"  compare 0= )
  assert( d => dynamicDog s" Woof!" compare 0= )
;                                      \ same for dynamic methods

main

```

Works with any ANS Forth

Needs the FMS-SI (single inheritance) library code located here: http://soton.mpeforth.com/flag/fms/index.html

```
include FMS-SI.f

:class animal
  variable cnt 0 cnt ! \ static instance variable
  :m init: 1 cnt +! ;m
  :m cnt: cnt @ . ;m
;class

:class cat <super animal
  :m speak ." meow" ;m
;class

:class dog <super animal
  :m speak ." woof" ;m
;class

cat Frisky   \ instantiate a cat object named Frisky
dog Sparky   \ instantiate a dog object named Sparky

\ The class method cnt: will return the number of animals instantiated
\ regardless of which animal object is used.

\ The instance method speak will respond differently depending
\ on the class of the instance object.

Frisky cnt:  \ => 2 ok
Sparky cnt:  \ => 2 ok
Frisky speak \ => meow ok
Sparky speak \ => woof ok

```

## Fortran

In modern Fortran a "derived type" concept corresponds to "class" in OOP. Such types have "type bound procedures", i.e. static methods. Procedure pointer components depend on the value of the object (so they are object-bound), can be redefined runtime and correspond approx to instances.

```
! type declaration
type my_type
 contains
procedure, pass :: method1
procedure, pass, pointer :: method2
end type my_type

! declare object of type my_type
type(my_type) :: mytype_object

!static call
 call mytype_object%method1() ! call method1 defined as subroutine
!instance?
 mytype_object%method2() ! call method2 defined as function

```

## FreeBASIC

```
' FB 1.05.0 Win64

Type MyType
  Public:
    Declare Sub InstanceMethod(s As String)
    Declare Static Sub StaticMethod(s As String)
  Private:
    dummy_ As Integer ' types cannot be empty in FB
End Type

Sub MyType.InstanceMethod(s As String)
  Print s
End Sub

Static Sub MyType.StaticMethod(s As String)
  Print s
End Sub

Dim t As MyType
t.InstanceMethod("Hello world!")
MyType.Staticmethod("Hello static world!")
Print
Print "Press any key to quit the program"
Sleep

```

Output:

```
Hello world!
Hello static world!

```

## FutureBasic

```
local fn FBClassDemo
  // Class
  ClassRef class = fn MutableStringClass
  // Cocoa base class name as human-readable string
  print fn StringFromClass( class )

  // Instantiate
  CFMutableStringRef mutStr = fn MutableStringNew

  // Method with single argument
  MutableStringSetString( mutStr, @"Hello, World!" )
  print mutStr

  // Method with multiple arguments
  MutableStringReplaceAllOccurrencesOfString( mutStr, @"World", @"Rosetta Code" )
  print mutStr
end fn

fn FBClassDemo

HandleEvents
```

Output:

```
NSMutableString
Hello, World!
Hello, Rosetta Code!

```

## Go

Go distances itself from the word "object" and from many object oriented concepts. It does however have methods. Any user-defined type in Go can have methods and these work very much like "instance methods" of object oriented languages. The examples below illustrate details of Go methods and thus represent the concept of instance methods.

```
type Foo int // some custom type

// method on the type itself; can be called on that type or its pointer
func (self Foo) ValueMethod(x int) { }

// method on the pointer to the type; can be called on pointers
func (self *Foo) PointerMethod(x int) { }

var myValue Foo
var myPointer *Foo = new(Foo)

// Calling value method on value
myValue.ValueMethod(someParameter)
// Calling pointer method on pointer
myPointer.PointerMethod(someParameter)

// Value methods can always be called on pointers
// equivalent to (*myPointer).ValueMethod(someParameter)
myPointer.ValueMethod(someParameter)

// In a special case, pointer methods can be called on values that are addressable (i.e. lvalues)
// equivalent to (&myValue).PointerMethod(someParameter)
myValue.PointerMethod(someParameter)

// You can get the method out of the type as a function, and then explicitly call it on the object
Foo.ValueMethod(myValue, someParameter)
(*Foo).PointerMethod(myPointer, someParameter)
(*Foo).ValueMethod(myPointer, someParameter)

```

Go has no direct equivalent to class methods as long as you think of a Go type as a class. A Go package however can be organized and used much like a class, and in this context, any function exported from the package works much like a class method.

An example package:

```
package box

import "sync/atomic"

var sn uint32

type box struct {
    Contents string
    secret uint32
}

func New() (b *box) {
    b = &box{secret: atomic.AddUint32(&sn, 1)}
    switch sn {
    case 1:
        b.Contents = "rabbit"
    case 2:
        b.Contents = "rock"
    }
    return
}

func (b *box) TellSecret() uint32 {
    return b.secret
}

func Count() uint32 {
    return atomic.LoadUint32(&sn)
}

```

Example use:

```
package main

import "box"

func main() {
    // Call constructor.  Technically it's just an exported function,
    // but it's a Go idiom to naming a function New that serves the purpose
    // of a constructor.
    b := box.New()

    // Call instance method.  In Go terms, simply a method.
    b.TellSecret()

    // Call class method.  In Go terms, another exported function.
    box.Count()
}

```

## Icon and Unicon

Icon does not have objects or methods; they can be implemented on top of other types such as records.

Unicon has no concept of static methods; all methods are normally invoked using an instance of a class. While it is technically possible to call a method without an instance, it requires knowledge of the underlying implementation, such as the name-mangling conventions, and is non-standard.

```
procedure main()

   bar := foo()  # create instance
   bar.m2()      # call method m2 with self=bar, an implicit first parameter

   foo_m1( , "param1", "param2")  # equivalent of static class method, first (self) parameter is null
end

class foo(cp1,cp2)
   method m1(m1p1,m1p2)
      local ml1
      static ms1
      ml1 := m1p1
      # do something
      return
   end
   method m2(m2p1)
      # do something else
      return
   end
initially
   L := [cp1]
end

```

## Haskell

Haskell doesn't have objects in OOP sence (i.e. first-class sitizens appearing in runtime with incapsulated state and ability to send messages (methods) to other objects).

Haskell has first-class immutable records with fields of any type, representing abstraction and incapsulation (due to purity). Polymorphism is implemented via type-classes, which are similar to OOP interfaces.

Dummy example:

```
data Obj = Obj { field :: Int, method :: Int -> Int }

-- smart constructor
mkAdder :: Int -> Obj
mkAdder x = Obj x (+x)

-- adding method from a type class
instanse Show Obj where
  show o = "Obj " ++ show (field o)

```

```
*Main> let o1 = Obj 1 (*5)
*Main> field o1
1
*Main> method o1 6
30
*Main> show o1
Obj 1

*Main> let o2 = mkAdder 5
*Main> field o2
5
*Main> method o2 6
11
*Main> show o2
Obj 5
```

## Haxe

```
class ExampleClass {
    public function exampleMethod() {
        return "This is a method!";
    }
    public function new() {}
}

class Main {
    static public function main():Void {
        var exampleObject = new ExampleClass();
        trace(exampleObject.exampleMethod());
    }
}

```

Output (Haxe interpreter, Haxe 4.3.7):

```
Main.hx:11: This is a method!

```

## J

Note: In some languages "everything is an object". This is not the case in J. In J, non-trivial objects will contain arrays. This is a relatively deep issue, beyond the scope of this page, except that: method invocations are relatively rare, in J.

All method invocations must contain two underline characters in J:

Static:

```
methodName_className_ parameters

```

and, given an object instance reference:

```
objectReference=:'' conew 'className'

```

an instance invocation could be:

```
methodName__objectReference parameters

```

Note that J also supports infix notation when using methods. In this case, there will be a second parameter list, on the left of the method reference.

```
parameters methodName_className_ parameters

```

or

```
parameters methodName__objectReference parameters

```

These variations might be useful when building combining words that need to refer to two different kinds of things. But mostly it's to be consistent with the rest of the language.

Finally, note that static methods can be referred to using the same notation as instance methods -- in this case you must have a reference to the class name:

```
classReference=: <'className'
methodName__classReference parameters

```

This might be useful when you are working with a variety of classes which share a common structure.

You can also refer to a dynamic method in the same fashion that you use to refer to a instance method -- in this case you must know the object name (which is a number). For example, to refer to a method on object 123

```
methodName_123_ parameters

```

This last case can be useful when debugging.

## Java

Static methods in Java are usually called by using the dot operator on a class name:

```
ClassWithStaticMethod.staticMethodName(argument1, argument2);//for methods with no arguments, use empty parentheses

```

Instance methods are called by using the dot operator on an instance:

```
ClassWithMethod varName = new ClassWithMethod();
varName.methodName(argument1, argument2);
//or
new ClassWithMethod().methodName(argument1, argument2);

```

Instance methods may not be called on references whose value is`null`(throws a`NullPointerException`).

Note: Static methods can also be called using the dot syntax on a reference to an instance, looking identical to an instance method call, but this is highly discouraged, and compilers usually complain about that (with a warning, not a failed compilation). The reason for this is that such a call is actually equivalent to a static method call on the static (compile-time) type of the reference in the source code. That means the runtime value of that reference is actually irrelevant, and the reference may be`null` or be a reference to an instance of a subclass, the compiler will still make it a call to the static method based on the class of the value at compile-time (i.e. inheritance does not apply; the method call is not resolved at runtime).

This means that there is no benefit to making a static method call this way, because one can make the call based on the static type that is already known from looking at the code when it is written. Furthermore, such a call may lead to serious pitfalls, leading one to believe that changing the object that it is called on could change the behavior. For example, a common snippet to sleep the thread for 1 second is the following:`Thread.currentThread().sleep(1000);`. However, since`.sleep()` is actually a static method, the compiler replaces it with`Thread.sleep(1000);`(since`Thread.currentThread()` has a return type of`Thread`). This makes it clear that the thread that is put to sleep is not under the user's control. However, written as`Thread.currentThread().sleep(1000);`, it may lead one to falsely believe it to be possible to sleep another thread by doing`someOtherThread.sleep(1000);` when in fact such a statement would also sleep the current thread.

## JavaScript

If you have a object called x and a method called y then you can write:

```
x.y()

```

## Julia

```
   module Animal

```

```
   abstract type Animal end
   abstract type Dog <: Animal end
   abstract type Cat <: Animal end

   struct Collie <: Dog
       name::String
       weight::Float64
   end

```

```
   struct Persian <: Cat
       name::String
       weight::Float64
   end

```

```
   #
   # This function is static: it works on any dog, even on a blank instance, in
   #   the same way, to produce the same output for anything that isa Dog in type.
   #
   function soundalert(a::T) where T <: Dog
       println("Woof!")
   end

```

```
   #
   # This function depends on the class instance's data for its value, so this type
   #   of function is one way to do an instance method in Jula.
   #
   masskg(x) = x.weight

```

## Kotlin

Kotlin does not have static methods, but they can be easily simulated by`companion object` methods.

```
class MyClass {
    fun instanceMethod(s: String) = println(s)

    companion object {
        fun staticMethod(s: String) = println(s)
    }
}

fun main() {
    val mc = MyClass()
    mc.instanceMethod("Hello instance world!")
    MyClass.staticMethod("Hello static world!")
}

```

Output:

```
Hello instance world!
Hello static world!

```

## Latitude

In Latitude, everything is an object. Being prototype-oriented, Latitude does not distinguish between classes and instances. Calling a method on either a class or an instance is done by simple juxtaposition.

```
myObject someMethod (arg1, arg2, arg3).
MyClass someMethod (arg1, arg2, arg3).
```

The parentheses on the argument list may be omitted if there is at most one argument and the parse is unambiguous.

```
myObject someMethod "string constant argument".
myObject someMethod (argument). ;; Parentheses are necessary here
myObject someMethod. ;; No arguments
```

Finally, a colon may be used instead of parentheses, in which case the rest of the line is considered to be the argument list.

```
myObject someMethod: arg1, arg2, arg3.
```

## LFE

LFE/Erlang doesn't have an object system. However, since LFE is a Lisp, one can do the same thing in LFE as one did in Lisps before CLOS: use closures to create and work with objects.

Not only that, but one may also use Erlang lightweight process to accomplish something very similar!

Examples for both approaches are given below.

### With Closures

```
(defmodule aquarium
 (export all))

(defun fish-class (species)
  "
  This is the constructor that will be used most often, only requiring that
  one pass a 'species' string.

  When the children are not defined, simply use an empty list.
  "
  (fish-class species ()))

(defun fish-class (species children)
  "
  This contructor is mostly useful as a way of abstracting out the id
  generation from the larger constructor. Nothing else uses fish-class/2
  besides fish-class/1, so it's not strictly necessary.

  When the id isn't know, generate one.
  "
  (let* (((binary (id (size 128))) (: crypto rand_bytes 16))
         (formatted-id (car
                         (: io_lib format
                           '"~32.16.0b" (list id)))))
    (fish-class species children formatted-id)))

(defun fish-class (species children id)
  "
  This is the constructor used internally, once the children and fish id are
  known.
  "
  (let ((move-verb '"swam"))
    (lambda (method-name)
      (case method-name
        ('id
          (lambda (self) id))
        ('species
          (lambda (self) species))
        ('children
          (lambda (self) children))
        ('info
          (lambda (self)
            (: io format
              '"id: ~p~nspecies: ~p~nchildren: ~p~n"
              (list (get-id self)
                    (get-species self)
                    (get-children self)))))
        ('move
          (lambda (self distance)
            (: io format
              '"The ~s ~s ~p feet!~n"
              (list species move-verb distance))))
        ('reproduce
          (lambda (self)
            (let* ((child (fish-class species))
                   (child-id (get-id child))
                   (children-ids (: lists append
                                   (list children (list child-id))))
                   (parent-id (get-id self))
                   (parent (fish-class species children-ids parent-id)))
              (list parent child))))
        ('children-count
          (lambda (self)
            (: erlang length children)))))))

(defun get-method (object method-name)
  "
  This is a generic function, used to call into the given object (class
  instance).
  "
  (funcall object method-name))

; define object methods
(defun get-id (object)
  (funcall (get-method object 'id) object))

(defun get-species (object)
  (funcall (get-method object 'species) object))

(defun get-info (object)
  (funcall (get-method object 'info) object))

(defun move (object distance)
  (funcall (get-method object 'move) object distance))

(defun reproduce (object)
  (funcall (get-method object 'reproduce) object))

(defun get-children (object)
  (funcall (get-method object 'children) object))

(defun get-children-count (object)
  (funcall (get-method object 'children-count) object))

```

With this done, one can create objects and interact with them. Here is some usage from the LFE REPL:

```
; Load the file and create a fish-class instance:

> (slurp '"object.lfe")
#(ok object)
> (set mommy-fish (fish-class '"Carp"))
#Fun<lfe_eval.10.91765564>

; Execute some of the basic methods:

> (get-species mommy-fish)
"Carp"
> (move mommy-fish 17)
The Carp swam 17 feet!
ok
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"

; Now let's look at "modifying" state data (e.g., children counts):

> (get-children mommy-fish)
()
> (get-children-count mommy-fish)
0
> (set (mommy-fish baby-fish-1) (reproduce mommy-fish))
(#Fun<lfe_eval.10.91765564> #Fun<lfe_eval.10.91765564>)
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"
> (get-id baby-fish-1)
"fdcf35983bb496650e558a82e34c9935"
> (get-children-count mommy-fish)
1
> (set (mommy-fish baby-fish-2) (reproduce mommy-fish))
(#Fun<lfe_eval.10.91765564> #Fun<lfe_eval.10.91765564>)
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"
> (get-id baby-fish-2)
"3e64e5c20fb742dd88dac1032749c2fd"
> (get-children-count mommy-fish)
2
> (get-info mommy-fish)
id: "47eebe91a648f042fc3fb278df663de5"
species: "Carp"
children: ["fdcf35983bb496650e558a82e34c9935",
           "3e64e5c20fb742dd88dac1032749c2fd"]
ok

```

### With Lightweight Processes

```
(defmodule object
 (export all))

(defun fish-class (species)
  "
  This is the constructor that will be used most often, only requiring that
  one pass a 'species' string.

  When the children are not defined, simply use an empty list.
  "
  (fish-class species ()))

(defun fish-class (species children)
  "
  This constructor is useful for two reasons:
    1) as a way of abstracting out the id generation from the
       larger constructor, and
    2) spawning the 'object loop' code (fish-class/3).
  "
  (let* (((binary (id (size 128))) (: crypto rand_bytes 16))
         (formatted-id (car
                         (: io_lib format
                           '"~32.16.0b" (list id)))))
    (spawn 'object
           'fish-class
           (list species children formatted-id))))

(defun fish-class (species children id)
  "
  This function is intended to be spawned as a separate process which is
  used to track the state of a fish. In particular, fish-class/2 spawns
  this function (which acts as a loop, pattern matching for messages).
  "
  (let ((move-verb '"swam"))
    (receive
      ((tuple caller 'move distance)
        (! caller (list species move-verb distance))
        (fish-class species children id))
      ((tuple caller 'species)
        (! caller species)
        (fish-class species children id))
      ((tuple caller 'children)
        (! caller children)
        (fish-class species children id))
      ((tuple caller 'children-count)
        (! caller (length children))
        (fish-class species children id))
      ((tuple caller 'id)
        (! caller id)
        (fish-class species children id))
      ((tuple caller 'info)
        (! caller (list id species children))
        (fish-class species children id))
      ((tuple caller 'reproduce)
        (let* ((child (fish-class species))
               (child-id (get-id child))
               (children-ids (: lists append
                               (list children (list child-id)))))
        (! caller child)
        (fish-class species children-ids id))))))

(defun call-method (object method-name)
  "
  This is a generic function, used to call into the given object (class
  instance).
  "
  (! object (tuple (self) method-name))
  (receive
    (data data)))

(defun call-method (object method-name arg)
  "
  Same as above, but with an additional argument.
  "
  (! object (tuple (self) method-name arg))
  (receive
    (data data)))

; define object methods
(defun get-id (object)
  (call-method object 'id))

(defun get-species (object)
  (call-method object 'species))

(defun get-info (object)
  (let ((data (call-method object 'info)))
    (: io format '"id: ~s~nspecies: ~s~nchildren: ~p~n" data)))

(defun move (object distance)
  (let ((data (call-method object 'move distance)))
    (: io format '"The ~s ~s ~p feet!~n" data)))

(defun reproduce (object)
  (call-method object 'reproduce))

(defun get-children (object)
  (call-method object 'children))

(defun get-children-count (object)
  (call-method object 'children-count))

```

Here is some usage from the LFE REPL:

```
; Load the file and create a fish-class instance:

> (slurp '"object.lfe")
#(ok object)
> (set mommy-fish (fish-class '"Carp"))
<0.33.0>

; Execute some of the basic methods:

> (get-species mommy-fish)
"Carp"
> (move mommy-fish 17)
The Carp swam 17 feet!
ok
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"

; Now let's look at modifying state data:

> (get-children mommy-fish)
()
> (get-children-count mommy-fish)
0
> (set baby-fish-1 (reproduce mommy-fish))
<0.34.0>
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"
> (get-id baby-fish-1)
"fdcf35983bb496650e558a82e34c9935"
> (get-children-count mommy-fish)
1
> (set baby-fish-2 (reproduce mommy-fish))
<0.35.0>
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"
> (get-id baby-fish-2)
"3e64e5c20fb742dd88dac1032749c2fd"
> (get-children-count mommy-fish)
2
> (get-info mommy-fish)
id: 47eebe91a648f042fc3fb278df663de5
species: Carp
children: ["fdcf35983bb496650e558a82e34c9935",
           "3e64e5c20fb742dd88dac1032749c2fd"]
ok

```

## Lingo

```
-- call static method
script("MyClass").foo()

-- call instance method
obj = script("MyClass").new()
obj.foo()
```

## Logtalk

In Logtalk, class or instance are roles that an object can play depending on the relations in other objects. Thus, a "class" can be defined by having an object specializing another object and an instance can be defined by having an object instantiating another object. Metaclasses are easily defined and thus a class method is just an instance method defined in the class metaclass.

```
% avoid infinite metaclass regression by
% making the metaclass an instance of itself
:- object(metaclass,
    instantiates(metaclass)).

    :- public(me/1).
    me(Me) :-
        self(Me).

:- end_object.

```

```
:- object(class,
    instantiates(metaclass)).

    :- public(my_class/1).
    my_class(Class) :-
        self(Self),
        instantiates_class(Self, Class).

:- end_object.

```

```
:- object(instance,
    instantiates(class)).

:- end_object.

```

Testing:

```
| ?- class::me(Me).
Me = class
yes

| ?- instance::my_class(Class).
Class = class
yes

```

## Lua

Lua does not provide a specific OO implementation, but its metatable mechanism and sugar for method-like calls does make it easy to implement and use such as system, as evidenced by its multitude of class libraries in particular.

Instance methods, in their most basic form, are simply function calls where the calling object reference is duplicated and passed as the first argument. Lua offers some syntactical sugar to facilitate this, via the colon operator:

```
local object = { name = "foo", func = function (self) print(self.name) end }

object:func() -- with : sugar
object.func(object) -- without : sugar

```

Using metatables, and specifically the __index metamethod, it is possible to call a method stored in an entirely different table, while still passing the object used for the actual call:

```
local methods = { }
function methods:func () -- if a function is declared using :, it is given an implicit 'self' parameter
    print(self.name)
end

local object = setmetatable({ name = "foo" }, { __index = methods })

object:func() -- with : sugar
methods.func(object) -- without : sugar

```

Lua does not have a specific way of handling static methods, but similarly to Go, they could simply be implemented as regular functions inside of a module.

Example module, named`box.lua`:

```
local count = 0
local box = { }
local boxmt = { __index = box }
function box:tellSecret ()
    return self.secret
end

local M = { }
function M.new ()
    count = count + 1
    return setmetatable({ secret = count, contents = count % 2 == 0 and "rabbit" or "rock" }, boxmt)
end
function M.count ()
    return count
end
return M

```

Example use:

```
local box = require 'box'

local b = box.new()

print(b:tellSecret())
print(box.count())

```

## M2000 Interpreter

In M2000 there are some kinds of objects. Group is an object. We can compose members to groups, with functions, operators, modules, events, and inner groups, among other members of type pointer to object. Another type is the COM type. Here we see the Group object

```
Module CheckIt {
      \\ A class definition is a function which return a Group
      \\ We can make groups and we can alter them using Group statement
      \\ Groups may have other groups inside

      Group Alfa {
      Private:
            myvalue=100
      Public:
            Group SetValue {
                  Set (x) {
                        Link parent myvalue to m
                        m<=x
                  }
            }
            Module MyMethod {
                 Read x
                 Print x*.myvalue
            }
      }

      Alfa.MyMethod 5 '500
      Alfa.MyMethod %x=200   ' 20000
      \\ we can copy Alfa to Z
      Z=Alfa
      Z.MyMethod 5
      Z.SetValue=300
      Z.MyMethod 5 ' 1500
      Alfa.MyMethod 5    ' 500
      Dim A(10)
      A(3)=Z
      A(3).MyMethod 5 '1500
      A(3).SetValue=200
      A(3).MyMethod 5 '1000
      \\ get a pointer of group in A(3)
      k->A(3)
      k=>SetValue=100
      A(3).MyMethod 5 '500
      \\ k get pointer to Alfa
      k->Alfa
      k=>SetValue=500
      Alfa.MyMethod 5 '2500
      k->Z
      k=>MyMethod 5 ' 1500
      Z.SetValue=100
      k=>MyMethod 5 ' 500
}
Checkit

```

## Maple

There is no real difference in how you call a static or instance method.

```
# Static
Method( obj, other, arg );

```

```
# Instance
Method( obj, other, arg );

```

## MiniScript

MiniScript uses prototype-based inheritance, so the only difference between a static method and an instance method is in whether it uses the`self` pseudo-keyword.

```
Dog = {}
Dog.name = ""
Dog.help = function()
    print "This class represents dogs."
end function
Dog.speak = function()
    print self.name + " says Woof!"
end function

fido = new Dog
fido.name = "Fido"

Dog.help    // calling a "class method"
fido.speak  // calling an "instance method"

```

Output:

```
This class represents dogs.
Fido says Woof!
```

## Nanoquery

```
class MyClass
	declare static id = 5
	declare MyName

	// constructor
	def MyClass(MyName)
		this.MyName = MyName
	end

	// class method
	def getName()
		return this.MyName
	end

	// static method
	def static getID()
		return id
	end
end

// call the static method
println MyClass.getID()

// instantiate a new MyClass object with the name "test"
// and call the class method
myclass = new(MyClass, "test")
println myclass.getName()
```

Output:

```
5
test
```

## Nemerle

```
// Static
MyClass.Method(someParameter);

// Instance
myInstance.Method(someParameter);

```

## NetRexx

Like Java, static methods in NetRexx are called by using the dot operator on a class name:

```
SomeClass.staticMethod()

```

Instance methods are called by using the dot operator on an instance:

```
objectInstance = SomeClass() -- create a new instance of the class
objectInstance.instanceMethod() -- call the instance method

SomeClass().instanceMethod() -- same as above; create a new instance of the class and call the instance method immediately

```

## Nim

In Nim there are no object methods, but regular procedures can be called with method call syntax:

```
var x = @[1, 2, 3]
add(x, 4)
x.add(5)

```

## OASYS Assembler

The OASYS runtime is strange; all classes share the same methods and properties, there are no static methods and properties, and there are no procedures/functions other than methods on objects. However, the initialization method can be called on a null object (no other method has this possibility).

The following code calls a method called &GO on the current object:

```
+&GO
```

## Objeck

```
ClassName->some_function(); # call class function
instance->some_method(); # call instance method
```

Objeck uses the same syntax for instance and class method calls. In Objeck, functions are the equivalent of public static methods.

## Object Pascal

Object Pascal as implemented in Delphi and Free Pascal supports both static (known in Pascal as class method) and instance methods. Free Pascal has two levels of static methods, one using the class keyword and one using both the class and the static keywords. A class method can be called in Pascal, while a static class method could be called even from C, that's the main difference.

```
// Static (known in Pascal as class method)
MyClass.method(someParameter);

// Instance
myInstance.method(someParameter);

```

## Objective-C

In Objective-C, calling an instance method is sending a message to an instance, and calling a class method is sending a message to a class object. Class methods are inherited through inheritance of classes. All messages (whether sent to a normal object or class object) are resolved dynamically at runtime, hence there are no "static" methods (see also: Smalltalk).

```
// Class
[MyClass method:someParameter];
// or equivalently:
id foo = [MyClass class];
[foo method:someParameter];

// Instance
[myInstance method:someParameter];

// Method with multiple arguments
[myInstance methodWithRed:arg1 green:arg2 blue:arg3];

// Method with no arguments
[myInstance method];

```

## OCaml

We can only call the method of an instantiated object:

```
my_obj#my_meth params

```

## Oforth

When a method is called, the top of the stack is used as the object on which the method will be applyed :

```
1.2 sqrt
```

For class methods, the top of the stack must be a class (which is also an object of Class class) :

```
Date now
```

## ooRexx

```
say "pi:" .circle~pi
c=.circle~new(1)
say "c~area:" c~area
Do r=2 To 10
 c.r=.circle~new(r)
 End
say .circle~instances('') 'circles were created'

::class circle
::method pi class -- a class method
  return 3.14159265358979323

::method instances class -- another class method
  expose in
  use arg a
  If datatype(in)<>'NUM' Then in=0
  If a<>'' Then
    in+=1
  Return in

::method init
  expose radius
  use arg radius
  self~class~instances('x')

::method area     -- an instance method
  expose radius
  Say self~class
  Say self
  return self~class~pi * radius * radius

```

Output:

```
pi: 3.14159265358979323
The CIRCLE class
a CIRCLE
c~area: 3.14159265
10 circles were created
```

## PascalABC.NET

```
type
  Point = auto class // class with autogenerated constructor
    x,y: real;
    static function RandomPoint := new Point(Random(-10..10),Random(-10..10));
    procedure Print;
    begin
      Writeln($'{x} {y}');
    end;
  end;

begin
  var p := new Point(2,3);
  p.Print; // instance method call
  p := Point.RandomPoint; // static method call
  p.Print;
end.

```

## Perl

```
# Class method
MyClass->classMethod($someParameter);
# Equivalently using a class name
my $foo = 'MyClass';
$foo->classMethod($someParameter);

# Instance method
$myInstance->method($someParameter);

# Calling a method with no parameters
$myInstance->anotherMethod;

# Class and instance method calls are made behind the scenes by getting the function from
# the package and calling it on the class name or object reference explicitly
MyClass::classMethod('MyClass', $someParameter);
MyClass::method($myInstance, $someParameter);

```

## Phix

Class methods are only "static" (not really a Phix term) if you don't override them. Phix does not demand that all routines be inside classes; traditional standalone routines are "static" in every sense. There is no way to call a class method without an instance, since "this" will typecheck even if not otherwise used.

```
without js -- (no class in p2js)
class test
    string msg = "this is a test"
    procedure show() ?this.msg end procedure
    procedure inst() ?"this is dynamic" end procedure
end class
test t = new()
t.show()            -- prints "this is a test"
t.inst()            -- prints "this is dynamic"
t.inst = t.show
t.inst()            -- prints "this is a test"

```

## PHP

```
// Static method
MyClass::method($someParameter);
// In PHP 5.3+, static method can be called on a string of the class name
$foo = 'MyClass';
$foo::method($someParameter);

// Instance method
$myInstance->method($someParameter);

```

## PicoLisp

Method invocation is syntactically equivalent to normal function calls. Method names have a trailing '>' by convention.

```
(foo> MyClass)
(foo> MyObject)
```

## Pike

Pike does not have static methods. (the`static` modifier in Pike is similar to`protected` in C++).

regular methods can be called in these ways:

```
obj->method();
obj["method"]();
call_function(obj->method);
call_function(obj["method"]);

```

`call_function()` is rarely used anymore.

because`()` is actually an operator that is applied to a function reference, the following is also possible:

```
function func = obj->method;
func();

```

as alternative to static function, modules are used. a module is essentially a static class. a function in a module can be called like this:

```
module.func();
module["func"]();

```

it should be noted that`module.func` is resolved at compile time while`module["func"]` is resolved at runtime.

## PL/SQL

```
create or replace TYPE myClass AS OBJECT (
    -- A class needs at least one member even though we don't use it
    dummy NUMBER,
    STATIC FUNCTION static_method RETURN VARCHAR2,
    MEMBER FUNCTION instance_method RETURN VARCHAR2
);
/
CREATE OR REPLACE TYPE BODY myClass AS
    STATIC FUNCTION static_method RETURN VARCHAR2 IS
    BEGIN
        RETURN 'Called myClass.static_method';
    END static_method;

    MEMBER FUNCTION instance_method RETURN VARCHAR2 IS
    BEGIN
        RETURN 'Called myClass.instance_method';
    END instance_method;
END;
/

DECLARE
    myInstance myClass;
BEGIN
    myInstance := myClass(null);
    DBMS_OUTPUT.put_line( myClass.static_method() );
    DBMS_OUTPUT.put_line( myInstance.instance_method() );
END;/

```

## Pluto

```
class myclass
    static function smethod() print("static method called") end

    function imethod() print("instance method called") end
end

myclass.smethod()
local mc = new myclass()
mc.imethod()

```

Output:

```
static method called
instance method called

```

## PowerShell

```
$Date = Get-Date
$Date.AddDays( 1 )
[System.Math]::Sqrt( 2 )

```

## Processing

```
// define a rudimentary class
class HelloWorld
{
    public static void sayHello()
    {
        println("Hello, world!");
    }
    public void sayGoodbye()
    {
        println("Goodbye, cruel world!");
    }
}

// call the class method
HelloWorld.sayHello();

// create an instance of the class
HelloWorld hello = new HelloWorld();

// and call the instance method
hello.sayGoodbye();
```

## Python

```
class MyClass(object):
	@classmethod
	def myClassMethod(self, x):
		pass
	@staticmethod
	def myStaticMethod(x):
		pass
	def myMethod(self, x):
		return 42 + x

myInstance = MyClass()

# Instance method
myInstance.myMethod(someParameter)
# A method can also be retrieved as an attribute from the class, and then explicitly called on an instance:
MyClass.myMethod(myInstance, someParameter)

# Class or static methods
MyClass.myClassMethod(someParameter)
MyClass.myStaticMethod(someParameter)
# You can also call class or static methods on an instance, which will simply call it on the instance's class
myInstance.myClassMethod(someParameter)
myInstance.myStaticMethod(someParameter)

```

## Quackery

Quackery is not an Object Oriented language. However it is possible to create a zen-like "distilled essence of object-orientation" in just a few lines of code.

Note that Quackery also does not have operator overloading (but see Modular arithmetic#Quackery for an illustration of how this can be achieved) so there is limited inheritance of methods possible - here only the methods`localise` and`delocalise` are common to all object types.

(It would be possible to extend this technique to a more fully-fledged object oriented system. See Dick Pountain's slim volume "Object Oriented FORTH: Implementation of Data Structures" (pub. 1987) for an example of doing so in Forth; a language to which Quackery is related, but slightly less amenable to such shenanigans.)

```
( ---------------- zen object orientation -------------- )

[ immovable
  ]this[ swap do ]done[ ] is object            (   -->   )

[ ]'[ ]                   is method            (   --> [ )

[ method
    [ dup share
      swap put ] ]        is localise          (   --> [ )

[ method [ release ] ]    is delocalise        (   --> [ )

( -------------- example: counter methods -------------- )

( to create a counter object, use:
           "[ object 0 ]  is 'name' ( [ -->   )"         )

[ method
    [ 0 swap replace ] ]  is reset-counter     (   --> [ )

[ method
    [ 1 swap tally ] ]    is increment-counter (   --> [ )

[ method [ share ] ]      is report-counter    (   --> [ )

( -------------------- demonstration ------------------- )

say 'Creating counter object: "mycounter".' cr cr
[ object 0 ]              is mycounter         ( [ -->   )

say "Initial value of mycounter: "
report-counter mycounter echo cr cr

say "Incrementing mycounter three times." cr
3 times [ increment-counter mycounter ]

say "Current value of mycounter: "
report-counter mycounter echo cr cr

say "Localising mycounter." cr cr
localise mycounter

say "    Current value of mycounter: "
report-counter mycounter echo cr cr

say "    Resetting mycounter." cr
reset-counter mycounter

say "    Current value of mycounter: "
report-counter mycounter echo cr cr

say "    Incrementing mycounter six times." cr
6 times [ increment-counter mycounter ]

say "    Current value of mycounter: "
report-counter mycounter echo cr cr

say "Delocalising mycounter." cr cr
delocalise mycounter

say "Current value of mycounter: "
report-counter mycounter echo cr cr

say "Resetting mycounter." cr
reset-counter mycounter

say "Current value of mycounter: "
report-counter mycounter echo cr cr
```

Output:

```
Creating counter object: "mycounter".

Initial value of mycounter: 0

Incrementing mycounter three times.
Current value of mycounter: 3

Localising mycounter.

    Current value of mycounter: 3

    Resetting mycounter.
    Current value of mycounter: 0

    Incrementing mycounter six times.
    Current value of mycounter: 6

Delocalising mycounter.

Current value of mycounter: 3

Resetting mycounter.
Current value of mycounter: 0
```

## Racket

The following snippet shows a call to the start method of the timer% class.

```
#lang racket/gui

(define timer (new timer%))
(send timer start 100)

```

## Raku

(formerly Perl 6)

Works with: Rakudo version 2015.12

### Basic method calls

```
class Thing {
  method regular-example() { say 'I haz a method' }

  multi method multi-example() { say 'No arguments given' }
  multi method multi-example(Str $foo) { say 'String given' }
  multi method multi-example(Int $foo) { say 'Integer given' }
};

# 'new' is actually a method, not a special keyword:
my $thing = Thing.new;

# No arguments: parentheses are optional
$thing.regular-example;
$thing.regular-example();
$thing.multi-example;
$thing.multi-example();

# Arguments: parentheses or colon required
$thing.multi-example("This is a string");
$thing.multi-example: "This is a string";
$thing.multi-example(42);
$thing.multi-example: 42;

# Indirect (reverse order) method call syntax: colon required
my $foo = new Thing: ;
multi-example $thing: 42;

```

### Meta-operators

The`.` operator can be decorated with meta-operators.

```
my @array = <a z c d y>;
@array .= sort;  # short for @array = @array.sort;

say @array».uc;  # uppercase all the strings: A C D Y Z

```

### Classless methods

A method that is not in a class can be called by using the`&` sigil explicitly.

```
my $object = "a string";  # Everything is an object.
my method example-method {
    return "This is { self }.";
}

say $object.&example-method;  # Outputs "This is a string."

```

## Red

```
;-object creation
my-proto: object [
	val1: 2
	val2: 3
	set: func [arg1 arg2] [self/val1: arg1 self/val2: arg2]
	sum: func [][ return (val1 + val2)]
]

;-create an instance
my-obj1: copy my-proto
;-calling internal method to get value
print my-obj1/sum

;-create a new instance
my-obj2: copy my-proto
;- calling an internal mathod to set value
my-obj2/set 1 1
;-calling the get method
print my-obj2/sum

;-calling the get method on the first object
print my-obj1/sum

```

## Ring

```
new point { print() }
Class Point
        x = 10  y = 20  z = 30
        func print see x + nl + y + nl + z + nl
```

```
o1 = new System.output.console
o1.print("Hello World")

Package System.Output
        Class Console
                Func Print cText
                        see cText + nl
```

## Ruby

```
# Class method
MyClass.some_method(some_parameter)

# Class may be computed at runtime
foo = MyClass
foo.some_method(some_parameter)

# Instance method
my_instance.a_method(some_parameter)

# The parentheses are optional
my_instance.a_method some_parameter

# Calling a method with no parameters
my_instance.another_method

```

## Rust

```
struct Foo;

impl Foo {
    // implementation of an instance method for struct Foo
    // returning the answer to life
    fn get_the_answer_to_life(&self) -> i32 {
        42
    }

    // implementation of a static method for struct Foo
    // returning a new instance object
    fn new() -> Foo {
        println!("Hello, world!");
        Foo // returning the new Foo object
    }
}

fn main() {
    // create the instance object foo,
    // by calling the static method new of struct Foo
    let foo = Foo::new();

    // get the answer to life
    // by calling the instance method of object foo
    println!("The answer to life is {}.", foo.get_the_answer_to_life());

    // Note that in Rust, methods still work on references to the object.
    // Rust will automatically do the appropriate dereferencing to get the method to work:
    let lots_of_references = &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&foo;
    println!("The answer to life is still {}." lots_of_references.get_the_answer_to_life());
}

```

## Scala

```
/* This class implicitly includes a constructor which accepts an Int and
 *  creates "val variable1: Int" with that value.
 */
class MyClass(val memberVal: Int) { // Acts like a getter, getter automatically generated.
  var variable2 = "asdf" // Another instance variable; a public mutable this time
  def this() = this(0) // An auxilliary constructor that instantiates with a default value
}

object HelloObject {
  val s = "Hello" // Not private, so getter auto-generated
}

/** Demonstrate use of our example class.
 */
object Call_an_object_method extends App {
  val s = "Hello"
  val m = new MyClass
  val n = new MyClass(3)

  assert(HelloObject.s == "Hello") // "Hello" by object getterHelloObject
  assert(m.memberVal == 0)
  assert(n.memberVal == 3)
  println("Successfully completed without error.")
}

```

## Sidef

```
class MyClass {
    method foo(arg) { say arg }
}

var arg = 42;

# Call a class method
MyClass.foo(arg);

# Alternatively, using an expression for the method name
MyClass.(:foo)(arg);

# Create an instance
var instance = MyClass();

# Instance method
instance.foo(arg);

# Alternatively, by using an expression for the method name
instance.(:foo)(arg);

# Alternatively, by asking for a method
instance.method(:foo)(arg);

```

## Smalltalk

In Smalltalk, calling an instance method is sending a message to an instance, and calling a class method is sending a message to a class object. Class methods are inherited through inheritance of classes. All messages (whether sent to a normal object or class object) are resolved dynamically at runtime, hence strictly speaking, there are no "static" methods. Often in literature, Smalltalk's class messages are described as synonymous to static function calls. This is wrong, because class methods can be overwritten in subclasses just as any other message. Classes are first class objects, meaning that references to them can be passed as argument, stored in other objects or returned as the result of a message send. This makes some of the common design patterns which deal with creation of objects trivial or even superfluous. (see also: ObjectiveC)

```
" Class "
MyClass selector: someArgument .
" or equivalently "
foo := MyClass .
foo selector: someArgument.

" Instance "
myInstance selector: someArgument.

" Message with multiple arguments "
myInstance fooWithRed:arg1 green:arg2 blue:arg3 .

" Message with no arguments "
myInstance selector.

" Binary (operator) message"
myInstance + argument .

```

Example for dynamic class determination:

```
theCar := (someCondition ifTrue:[ Ford ] ifFalse: [ Jaguar ]) new.

```

Message names (selectors) can be chosen or constructed dynamically at runtime. For example:

```
whichMessage := #( #'red' #'green' #'blue') at: computedIndex.
foo perform: whichMessage

```

or:

```
theMessage := ('handleFileType' , suffix) asSymbol.
foo perform: theMessage.

```

This is often sometimes used as a dispatch mechanism (also, to implement state machines, for example).

Of course, especially with all that dynamics, a selector for an unimplemented message might be encountered. This raises a MessageNotUnderstood exception (runtime exception).

```
[
    foo perform: theMessage
] on: MessageNotUnderstood do:[
   Dialog information: 'sorry'
]

```

## SuperCollider

In SuperCollider, classes are objects. To call a class or object method, a message is passed to the class or the object instance. In the implementation, class method names are prefixed with an asterix, all other methods are instance methods.

```
	SomeClass {

		*someClassMethod {

		}

		someInstanceMethod {

		}

	}

	SomeClass.someClassMethod;

	a = SomeClass.new;
	a.someInstanceMethod;

```

## Swift

In Swift, instance methods can be declared on structs, enums, and classes. "Type methods", which include static methods for structs and enums, and class methods for classes, can be called on the type. Class methods are inherited through inheritance of classes, and are resolved dynamically at runtime like instance methods. (see also: Smalltalk).

```
// Class
MyClass.method(someParameter)
// or equivalently:
let foo = MyClass.self
foo.method(someParameter)

// Instance
myInstance.method(someParameter)

// Method with multiple arguments
myInstance.method(red:arg1, green:arg2, blue:arg3)

```

## Tcl

```
package require Tcl 8.6
# "Static" (on class object)
MyClass mthd someParameter

# Instance
$myInstance mthd someParameter

```

## TXR

TXR Lisp method invocation syntax is`obj.(method args...)`.

Static methods are just functions that don't take an object as an argument. The above notation, therefore, normally isn't used, rather the functional square brackets:`[obj.function args...]`.

The`defstruct` clause`:method` is equivalent to`:function` except that it requires at least one argument, the leftmost one denoting the object.

The`obj.(method args...)` could be used to call a static function; it would pass`obj` as the leftmost argument. Vice versa, the square bracket call notation can be used to invoke a method; the object has to be manually inserted:`[obj.function obj args...]`.

```
(defvarl thing-count 0)

(defstruct thing ()
  (call-count 0)

  (:init (me)
    (inc thing-count))
  (:function get-thing-count () thing-count)
  (:method get-call-count (me) (inc me.call-count)))

(let ((t1 (new thing))
      (t2 (new thing)))
  (prinl t1.(get-call-count)) ;; prints 1
  (prinl t1.(get-call-count)) ;; prints 2
  (prinl t1.(get-call-count)) ;; prints 3
  (prinl t2.(get-call-count)) ;; prints 1
  (prinl t2.(get-call-count)) ;; prints 2
  (prinl t2.(get-call-count)) ;; prints 3

  (prinl [t1.get-thing-count])  ;; prints 2
  (prinl [t2.get-thing-count])) ;; prints 2
```

Output:

```
1
2
3
1
2
3
2
2
```

## Ursa

```
# create an instance of the built-in file class
decl file f

# call the file.open method
f.open "filename.txt"
```

## VBA

First we have to create a class module named "myObject" :

```
Option Explicit

Sub Method_1(Optional myStr As String)
Dim strTemp As String
    If myStr <> "" Then strTemp = myStr
    Debug.Print strTemp
End Sub

Static Sub Method_2(Optional myStr As String)
Dim strTemp As String
    If myStr <> "" Then strTemp = myStr
    Debug.Print strTemp
End Sub

```

In a "standard" Module, the call should be :

```
Option Explicit

Sub test()
Dim Obj As New myObject
    Obj.Method_1 "Hello to you"
    Obj.Method_2 "What is your name ?"
    Obj.Method_1
    Obj.Method_2
End Sub

```

Output:

```
Hello to you
What is your name ?

What is your name ?
```

## V (Vlang)

Vlang uses objects without classes (sometimes known as class-free or classless):

1) Structs can have methods assigned to them or be embedded in other structs.

2) Vlang also uses modules. Functions and structs can be exported from a module, which works somewhat similar to the class method.

```
// Assigning methods to structs
struct HelloWorld {}

// Method's in Vlang are functions with special receiver arguments at the front (between fn and method name)
fn (sh HelloWorld) say_hello() {
	 println("Hello, world!")
}

fn (sb HelloWorld) say_bye() {
	 println("Goodbye, world!")
}

fn main() {

	//  instantiate object
	hw := HelloWorld{}

	// call methods of object
	hw.say_hello()
	hw.say_bye()
}

```

Output:

```
Hello, world!
Goodbye, world!

```

Exporting functions from modules:

Create a module:

```
// myfile.v
module mymodule

// Use "pub" to export a function
pub fn say_hi() {
	println("hello from mymodule!")
}
```

Import and use the module's function in your code:

```
import mymodule

fn main() {
	mymodule.say_hi()
}
```

Output:

```
hello from mymodule!

```

## Wren

Note that it's possible in Wren for instance and static methods in the same class to share the same name. This is because static methods are considered to belong to a separate meta-class.

```
class MyClass {
    construct new() {}
    method() { System.print("instance method called") }
    static method() { System.print("static method called") }
}

var mc = MyClass.new()
mc.method()
MyClass.method()
```

Output:

```
instance method called
static method called

```

## XBS

You can call object methods using two types of structures. Classes and Objects.

### Classes

```
class MyClass {
	construct=func(self,Props){
		self:Props=Props;
	}{Props={}}
	GetProp=func(self,Name){
		send self.Props[Name];
	}
}

set Class = new MyClass with [{Name="MyClass Name"}];
log(Class::GetProp("Name"));
```

Output:

```
MyClass Name

```

### Objects

```
set MyObj = {
	a=10;
	AddA=func(self,x){
		send self.a+x;
	};
}

log(MyObj::AddA(2));
```

Output:

```
12

```

## XLISP

Class methods and instance methods are defined using DEFINE-CLASS-METHOD and DEFINE-METHOD respectively. They are called by sending a message to the class or to an instance of it: the message consists of (a) the name of the object that will receive it, which may be a class; (b) the name of the method, as a quoted symbol; and (c) the parameters if any.

```
(DEFINE-CLASS MY-CLASS)

(DEFINE-CLASS-METHOD (MY-CLASS 'DO-SOMETHING-WITH SOME-PARAMETER)
    (DISPLAY "I am the class -- ")
    (DISPLAY SELF)
    (NEWLINE)
    (DISPLAY "You sent me the parameter ")
    (DISPLAY SOME-PARAMETER)
    (NEWLINE))

(DEFINE-METHOD (MY-CLASS 'DO-SOMETHING-WITH SOME-PARAMETER)
    (DISPLAY "I am an instance of the class --  ")
    (DISPLAY SELF)
    (NEWLINE)
    (DISPLAY "You sent me the parameter ")
    (DISPLAY SOME-PARAMETER)
    (NEWLINE))

(MY-CLASS 'DO-SOMETHING-WITH 'FOO)

(DEFINE MY-INSTANCE (MY-CLASS 'NEW))

(MY-INSTANCE 'DO-SOMETHING-WITH 'BAR)
```

Output:

```
I am the class -- #<Class:MY-CLASS #x38994c8>
You sent me the parameter FOO
I am an instance of the class --  #<Object:MY-CLASS #x39979d0>
You sent me the parameter BAR
```

## Zen C

```
struct MyStruct {}

impl MyStruct {
    fn static_method() {
        println "static method called";
    }

    fn method(self) {
        println "instance method called";
    }
}

fn main() {
    let mc = MyStruct{};
    mc.method();
    MyStruct::static_method();
}
```

Output:

```
instance method called
static method called

```

## Zig

Zig does not have classes nor objects. Zig's structs, however, can have methods; but they are not special. They are only namespaced functions that can be called with dot syntax.

```
const testing = @import("std").testing;

pub const ID = struct {
    name: []const u8,
    age: u7,

    const Self = @This();

    pub fn init(name: []const u8, age: u7) Self {
        return Self{
            .name = name,
            .age = age,
        };
    }

    pub fn getAge(self: Self) u7 {
        return self.age;
    }
};

test "call an object method" {
    // Declare an instance of a struct by using a struct method.
    const person1 = ID.init("Alice", 18);

    // Or by declaring it manually.
    const person2 = ID{
        .name = "Bob",
        .age = 20,
    };

    // test getAge() method call
    try testing.expectEqual(@as(u7, 18), person1.getAge());
    try testing.expectEqual(@as(u7, 20), ID.getAge(person2));
}
```

## zkl

In zkl, a class can be static (there will only exist one instance of the class). A function is always a member of some class but will only be static if it does not refer to instance data.

```
class C{var v; fcn f{v}}
C.f() // call function f in class C
C.v=5; c2:=C();    // create new instance of C
println(C.f()," ",c2.f()) //-->5 Void
C.f.isStatic //--> False

class [static] D{var v=123; fcn f{v}}
D.f(); D().f(); // both return 123
D.f.isStatic //-->False

class E{var v; fcn f{}} E.f.isStatic //-->True
```

Retrieved from " https://rosettacode.org/wiki/Call_an_object_method?oldid=400434"

Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Search

7. Monkey Documentation
   URL: https://regal-internet-brothers.github.io/monkey/docs/Programming_Language%20reference.html
   Monkey Documentation

# Monkey language reference

This manual describes the syntax and general concepts behind the core Monkey language.

## Contents

About this reference Programs and declarations Strict mode Comments Identifiers Types Variables Constants Expressions Statements Functions Methods Classes Generics Interfaces Exceptions Modules Public and private External declarations Memory management Preprocessor

## About this reference

A monospaced font is used for program code examples, for example:

`Function``Main``()``Print``"Hello World!"``End`

Language syntax explanations are generally formatted as follows:

- Anything that appears in bold indicates literal text. For example: Function means the actual text 'Function'.
- Anything that appears in italics indicates other syntax. For example: Identifier means any text that is a valid identifier.
- Anything that appears in square brackets [ ] is optional. For example: [ Step ] means the literal text Step is optional.
- The pipe character | is use for alternatives. For example: To | Until means you can use To or Until - but not both.
- A three dots ellipsis is used to indicate repetition.

These rules are not strictly followed. Where it makes sense to do so, syntax may be shown in a simplified form with explanatory notes.

## Programs and declarations

A Monkey program consists of one or more modules, each of which is a separate file, consisting of a series of declarations.

A declaration associates a 'meaning' with an identifier. For example, this declaration...

`Global``x``:``Int`

...indicates that the identifier 'x' is a global variable of type 'Int' (an integer).

Monkey supports the following kinds of declarations:

- Modules
- Constants
- Local, Global and Field variables
- Classes
- Functions
- Methods

A module is itself a kind of declaration and is represented by a single source file. The name of the module is taken from the name of the source file. For example, if your file is named "particles.monkey" then the module will be called "particles".

Modules may 'import' other modules, which may in turn import other modules and so on.

Every Monkey program has a 'main module' that must contain a public function called Main that takes no parameters and returns an integer. For example:

`Function``Main``()``Print``"That's all folks!"``End`

This is the entry point of the program and is where program execution begins.

If you are using the mojo framework of modules, you must create a new class (which extends the base mojo.app class) and create a new instance of it in the Main function. See the mojo.app Module Reference for more information. An example of this is:

`Import``mojo.app``Import``mojo.graphics``Class``MyApp``Extends``App``Method``OnRender``()``DrawText``"Hello World!"``,``0``,``0``End``End``Function``Main``()``New``MyApp``End`

## Strict mode

By default, Monkey allows you to take certain shortcuts when programming.

However, Monkey also offers a special Strict mode for programmers who prefer a stricter language definition.

The differences between strict and non-strict mode are:

- In non-strict mode, variable type, function return type and function parameter types can be optionally omitted. In this case they will default to Int. In strict mode, you must always specify the type of all variables, functions return values and function parameters.
- In non-strict mode, Return statements can be omitted at the end of a function. In this case, a Return statement will be automatically generated that will return an appropriate default value for the function type. That is, False for bool, 0 for int and float, "" for string, [] for arrays and Null for objects. In strict mode, a function that does not return Void must end with a Return statement.
- In non-strict mode, the brackets around function call parameters are optional if the function is being used as a statement, or if the function can be called with no parameters. In strict mode, all function call parameters must be enclosed in brackets.

To use strict mode, a Strict directive must be placed at the very top of your module. For example:

`Strict``Function``Main``:``Int``()                     ``'in Strict mode, the :Int type definition is compulsory``Print``( ``"Strict mode is...strict!"`` )  ``'in Strict mode, all function calls require brackets.``Return``0``'in strict mode, we MUST return a value.``End`

The examples in this document will be presented in non-strict form.

## Comments

You can add line comments to your programs using the ' (apostrophe) character. Everything following the ' character until the end of the line will be ignored.

You can add block comments to your programs using #rem and #end. These must appear at the start of a new line, although they may optionally have whitespace characters in front. Everything between #rem and #end will be ignored. Block comments can also be nested.

Here is an example of using comments:

`Print``"Hello World"``'This is a line comment!``#Rem 'start of a block comment``Print "The sound of silence!" 'inside a block comment``#End`

## Identifiers

Identifiers must start with an alphabetic character, or a single underscore followed by an alphabetic character. The rest of the identifier may contain any combination of alphanumeric characters and/or underscores.

Identifiers are case sensitive (except for language keywords - see below). For example, player, Player, PLAYER and PLayER are all different identifiers. This allows you to reuse the same name for different purposes. For example, Actor may refer to a class while actor refers to an object of that class.

Here are some examples of valid Monkey identifiers:

`score``player1``player_up``_internal``helloworld``HelloWorld`

### Language keywords and reserved identifiers

The following identifiers are language keywords and are reserved for use by the Monkey language:

`Void``Strict``Public``Private``Property``Bool``Int``Float``String``Array``Object``Mod``Continue``Exit``Import``Extern``New``Self``Super``Try``Catch``Eachin``True``False``Not``Extends``Abstract``Final``Select``Case``Default``Const``Local``Global``Field``Method``Function``Class``And``Or``Shl``Shr``End``If``Then``Else``ElseIf``EndIf``While``Wend``Repeat``Until``Forever``For``To``Step``Next``Return``Module``Interface``Implements``Inline``Throw`

Language keywords are case insensitive - for example, you may use the keyword function, Function or indeed even fUNCTION (not recommended) to declare a function.

The keywords Module, Inline and Array are not currently used by the Monkey language but are reserved for future use.

### Monkey naming conventions

The standard Monkey modules use a simple naming convention:

- All-caps case (eg: 'ALLCAPS' ): Constants.
- Pascal case (eg: 'PascalCase' ): Globals, functions, class, methods, properties.
- Camel case (eg: 'camelCase' ): Fields, locals and function parameters.

You are of course free to use your own convention, but for the sake of consistency it is recommended that this convention be used for the public interface of any modules you create intended for use by the Monkey community.

## Types

Monkey is a statically typed language, which means that all variables, function parameters, function return values and expressions have an associated type that is known at compile time.

The following types are supported:

Boolean Integer Floating point String Array Object

### The Bool type

Values of type Bool are boolean values used to express the result of conditional expressions, such as the comparison operators, and to represent a true/false 'state' in general. A boolean value can only be either True or False.

The syntax used for declaring values and variables of boolean type is Bool. For example:

`Local``gamePaused``:``Bool`` = ``False`

Boolean values are usually generated by the use of the comparison operators, for example:

`If``livesLeft``<>``0``doSomething``()``End`

However, in some circumstances Monkey will automatically convert a non-bool value to bool. This will occur when evaluating an expression for use with the If or While statements; the Until part of a Repeat loop; and when evaluating the arguments for the Not, Or and And operators. For example:

`If``livesLeft``doSomething``()``End`

See the conversions section in the expressions chapter for more information.

Also, notice that the Bool identifiers can also be declared by using the ? character. This two lines of source code are both valid and syntactically correct:

`Local``myVariable``:``Bool`` = ``True``Local``myVariable``? = ``True`

### The Int type

Values of type Int are signed integer values - that is, values with no fractional part. The range of integer values supported is target dependent, but is at least 32 bits. A 32 bit int can represent a range of values from: -2,147,483,648 to 2,147,483,647

The syntax used for declaring values and variables of integer type is Int. For example:

`Local``x``:``Int`` = ``5`

Integer literals are sequences of digits without a fractional part. Hexadecimal literals are also supported with the $ prefix. For example, the following are all valid integer literals:

`0``1234``$3D0DEAD``$CAFEBABE`

Also, notice that integer identifiers can also be declared by using the % character. This two lines of source code are both valid and syntactically correct:

`Local``myVariable``:``Int`` = ``1024``Local``myVariable``% = ``1024`

### The Float type

Values of type Float are signed numeric values with both an integer and fractional part. The range of floating point values support is target dependent, but is at least 32 bits.

The syntax used for declaring values and variables of floating point type is Float. For example:

`Local``gravity``:``Float`` = ``9.81`

Floating point literals are sequences of digits that include a fractional part, for example:

`.0``0.0``.5``0.5``1.0``1.5``1.00001``3.14159265`

Also, notice that floating point identifiers can also be declared by using the # character. This two lines of source code are both valid and syntactically correct:

`Local``myVariable``:``Float`` = ``3.141516``Local``myVariable``# = ``3.141516`

### The String type

Values of type String are used to represent sequences of characters, such as text. The size of each character in a string value is target dependent, but is at least 8 bits.

The syntax used for declaring values and variables of string type is String. For example:

`Local``name``:``String`` = ``"John Smith"`

Strings are immutable meaning that once they are created they cannot be modified. Operations that 'modify' a string will always return a new string.

String literals are sequences of characters enclosed in "" (quotation marks). String literals may also include escape sequences - special sequences of characters used to represent unprintable characters.

You can use the following escape sequences in string literals:

| Escape sequence | Character code |
| --- | --- |
| `~q` | 34 (quotate mark ") |
| `~n` | 10 (newline) |
| `~r` | 13 (return) |
| `~t` | 9 (tab) |
| `~z` | 0 (null> |
| `~~` | 126 (tilde ~) |

Here are some examples of string literals:

`"Hello World"``"~qHello World~q"``"~tIndented~n"`

Strings can also be indexed and sliced.

The syntax for indexing a string is: StringExpression [ IndexExpression ]

Indexing a string returns the character code of the character at IndexExpression. Index 0 is the first character in the string.

IndexExpression must be greater than or equal to 0 and less than the length of StringExpression otherwise an error occurs.

Here are some examples of indexing a string:

`Print``"ABC"``[``0``]              ``'prints 65 - the character code of 'A'``Print``"ABC"``[``1``]              ``'prints 66 - the character code of 'B'``Print``"Hi~n"``[``2``]             ``'prints 10 - the character code of '~n'`

The syntax for slicing a string is: StringExpression[ StartExpression..EndExpression ]

Slicing a string returns a new string consisting of the characters within StringExpression starting at index StartExpression and ending at index EndExpression.

Both StartExpression and EndExpression are optional. If StartExpression is omitted, it defaults to 0. If EndExpression is omitted, it defaults to the length of the string.

StartExpression and EndExpression can also be negative, in which case they refer to offsets from the end of the string.

Here are some examples of slicing a string:

`Print``"Hello World"``[``4``.``.7``]   ``'prints "o W'``Print``"Hello World"``[.``.5``]    ``'prints "Hello"``Print``"Hello World"``[``5``..]    ``'prints "World"``Print``"Hello World"``[..]     ``'prints "Hello World"`

Strings also support a number of 'pseudo' methods and functions:

| Method/Function | Description |
| --- | --- |
| Method Length() Property | Returns the number of characters in the string. |
| Method Compare( str:String ) | Returns a value <0 if the current string is less than str, a value>0 if the current string is greater than str or 0 if this string is equal to str. |
| Method Find( subString:String ) | Returns the index of the first occurance of subString within the current string. |
| Method Find( subString:String, startIndex ) | Returns the index of the first occurance of subString within the current string, starting at index startIndex. |
| Method FindLast( subString:String ) | Returns the index of the last occurance of subString within the current string. |
| Method FindLast( subString:String, startIndex ) | Returns the index of the last occurance of subString within the current string, starting at index startIndex. |
| Method Contains( subString:String ) | Returns true if the current string contains subString. |
| Method StartsWith( subString:String ) | Returns true if the current string starts with subString. |
| Method EndsWith( subString:String ) | Returns true if the current string ends with subString. |
| Method ToLower:String() | Returns the current string converted to lowercase. |
| Method ToUpper:String() | Returns the current string converted to uppercase. |
| Method Trim:String() | Returns the current string with all leading and trailing whitespace characters removed. |
| Method Split:String[]( separator:String ) | Returns an array of strings that contains the substrings in the current string deliminated by separator. |
| Method ToChars:Int[]() | Converts string to an array of character codes. |
| Method Join:String( pieces:String[] ) | Returns the elements of pieces concatened together with the current string inserted between each substring. |
| Function FromChar:String( char ) | Returns a string of length 1 consisting of a single character code. |
| Function FromChars:String( chars:Int[] ) | Creates a string from an array of character codes. |

For example:

`Print``"  Hello World  ~n"``.``Trim``()    ``'prints "Hello World"``Print``"Hello World"``.``ToUpper``()       ``'prints "HELLO WORLD"`

Also, notice that string identifiers can also be declared by using the $ character. This two lines of source code are both valid and syntactically correct:

`Local``message``:``String`` = ``"Hello world"``Local``message``$ = ``"Hello world"`

### The Array type

An array is a linear sequence of values that can be addressed using an integer index.

Each array has an associated element type - that is, the type of the elements actually contained in the array. Due to the nature of Monkey, an array's element type is a purely static property. It is only known at compile time so arrays cannot be downcast at runtime.

The syntax used for declaring values and variables of array type is: ElementType []

For example:

`Local``box``:``Int``[]            ``'an array of ints``Local``ratio``:``Float``[]        ``'an array of floats``Local``thing``:``Int``[][]        ``'an array of arrays of ints`

An array literal is a (possibly empty) comma separated sequence of expressions enclosed with [ and ]. The expressions used in an array literal must be of the same type. For example:

`Local``box``:``Int``[]=[]                              ``'an empty array literal``Local``scores``:``Int``[]=[``10``,``20``,``30``]                   ``'a comma separated sequence``Local``text``:``String``[]=[``"Hello"``,``"There"``,``"World"``]   ``'a comma separated sequence`

The syntax for indexing an array is: ArrayExpression [ IndexExpression ]. For example:

`Local``score``:``Int``[]=[``10``,``20``,``30``]    ``'a comma separated sequence``Print``score``[``1``]                  ``'prints "20"`

Indexing an array yields a 'pseudo variable' of the array's element type that can be both read from and written to.

IndexExpression must be an integer expression greater than or equal to 0 and less than the length of the array otherwise an error occurs.

Like strings, arrays can also be sliced. The syntax for slicing an array is: ArrayExpression [ StartExpression .. EndExpression ].

Slicing an array returns 'sub array' of ArrayExpression starting at index StartExpression and ending at index EndExpression.

Both StartExpression and EndExpression are optional. If StartExpression is omitted, it defaults to 0. If EndExpression is omitted, it defaults to the length of the array.

StartExpression and EndExpression can also be negative, in which case they refer to offsets from the end of the array.

Here is an example of slicing an array:

`Local``text``:``String``[]=[``"Cruel"``,``"Hello"``,``"World"``,``"There"``]    ``'a comma separated sequence``Local``helloWorld``:=``text``[``1``.``.3``]                             ``'contains ["Hello","World"]`

Arrays also support a number of pseudo methods:

| Method | Description |
| --- | --- |
| Method Length() Property | The number of elements in the array. |
| Method Resize:Array( newLength ) | Copies the first newLength elements of the current array into a new array of length newLength, and returns the new array. |

For example:

`Local``text``:``String``[]=[``"Hello"``,``"There"``,``"World"``]        ``'a comma separated sequence``Print``text.Length``'prints '3'``text``=``text.Resize``( ``2`` )``Print``text.Length``'prints '2'`

### The Object type

An object is an instance of a class, and contains a set of constants, variables, methods and functions.

The syntax used for declaring values and variables of object type is: ClassIdentifier

For example:

`Local``mine``:``MyClass`` = ``New``MyClass`

Please see the classes section for more information on declaring classes and creating objects.

## Variables

A variable is a storage location used to hold values that change while your program runs.

All variables have an identifier, a type, and an optional initializer - an expression used to set the variable to an initial value.

The type of a variable can either be declared literally, or can be deduced from the variable's initializer.

### Local variables

Local variables are temporary variables that disappear when the local scope they are declared in is destroyed.

Local variables may be declared within any local scope.

Each of the following creates a local scope:

- The statements inside a function or method.
- The statements inside an If, Else If or If block.
- The statements inside a Case or Default block.
- The statements inside a While, Repeat or For loop.

The syntax for declaring a local variable is:

Local Identifier : Type [ = Expression ]

Or...

Local Identifier := Expression

For example:

`Local``age``:``Int``=``10``Local``age``:=``10`

### Global variables

Global variables are variables that persist during the execution of your program.

Global variables may be declared at module scope, or within a class declaration.

The syntax for declaring a global variable is:

Global Identifier : Type [ = Expression ]

Or...

Global Identifier := Expression

For example:

`Global``isPlayerAlive``:``Bool`` = ``True`

### Field variables

Field variables are variables that persist as long as the object they belong to.

Field variables can only be declared within a class declaration.

The syntax for declaring a field variable is:

Field Identifier : Type [ = Expression ]

Or...

Field Identifier := Expression

## Constants

A constant is a value that is evaluated at compile time, and that does not change throughout the execution of a program.

Constants may be declared at module scope, within class scope or within any local scope.

The syntax for declaring a constant is:

Const Identifier : Type = Expression

Or...

Const Identifier := Expression

## Expressions

Expressions are the parts of a program that perform calculations, make logical comparisons and return values from methods or functions.

### Operators

| Operator Syntax | Description |
| --- | --- |
| `New` ClassType | Create a new Object |
| `Null` | The null object |
| `True` | Boolean true |
| `False` | Boolean false |
| `Self` | Self |
| `Super` | Super |
| Literal | Literal |
| Identifier | Identifier |
| `.` Identifier | Scope member access |
| `(` ExpressionSeq`)` | Invoke |
| `[` Expression`]` | Index |
| `+` | Unary plus |
| `-` | Unary minus |
| `~` | Bitwise complement |
| `Not` | Boolean inverse |
| `*` | Multiplication |
| `/` | Division |
| `Mod` | Modulus |
| `Shl` | Bitwise shift left |
| `Shr` | Bitwise shift left (signed) |
| `+` | Addition |
| `-` | Subtraction |
| `&` | Bitwise 'and' |
| `~` | Bitwise 'xor' |
| `|` | Bitwise 'or' |
| `=` | Equals |
| `<` | Less than |
| `>` | Greater than |
| `<=` | Less than or equals |
| `>=` | Greater than or equals |
| `<>` | Not equals |
| `And` | Condititonal 'and' |
| `Or` | Conditional 'or' |

Operators are grouped by priority.

### Balancing argument types

When performing binary arithmetic (*, /, Mod, +, -) or comparison operations (=, <, >, <=, >=, <>), operator arguments are 'balanced' according to the following rules:

- If either operand is not string, float or int, then error,
- else if either operand is a string, then the balanced type is string,
- else if either operand is a float, then the balanced type is float,
- else the balanced type is int.

In the case of arithmetic operations, arguments are first implicitly converted to the balanced type if necessary, and the result is also of the balanced type.

In the case of comparison operations, arguments are first implicitly converted to the balanced type if necessary, and the result is boolean.

The only valid arithmetic operation that can be performed on strings is addition, which performs string concatentation on the arguments.

### Conditional operators

The arguments of conditional operations (And, Or) are first converted to boolean if necessary and the result is boolean.

In the case of Or, if the left-hand-side expression evaluates to true, the right-hand-side expression is not evaluated.

For example:

`If``car``<>``Null``Or``GetSpeed``()>``10``Then...`

In the above example, if car is not Null, then the right-hand-side of the Or is not evaluated - ie: the GetSpeed function is never called.

In the case of And, if the left-hand-side expression evaluates to false, the right-hand-side expression is not evaluated.

For example:

`If``enemies.Count`` > ``0``And``HasEnemyInSight``() ``Then`` ...`

In the above example, if enemies.Count is <= 0, then the right-hand-side of the And is not evaluated - ie: the hasEnemyInSight function is never called.

### Bitwise operators

When performing bitwise (Shl Shr & | ~) operations, arguments are first implicitly converted to integers if necessary before the operation is performed. The result is also an integer.

### Implicit conversions

Implicit conversions are automatic conversions performed when assigning a value to a variable, passing parameters to a function, returning a value from a function or when balancing operator operands.

Monkey supports the following implicit conversions:

| Source type | Target type | Notes |
| --- | --- | --- |
| Boolean | Integer | Return 1 if boolean value is true, 0 if false. |
| Integer | Floating point |
| Integer | String |
| Floating point | Integer | Value is converted by discarding fractional part. |
| Floating point | String | Conversion is target dependent. |
| Derived class object | Base class object | Upcast operation. |

### Explicit conversions

Explicit conversions are conversions from one type to another type which can be performed manually by the programmer .

The syntax for performing an explicit conversion is: TargetType ( Expression )

For example:

`Local``energyFloat``:``Float`` = ``120.1000002001``Local``energyInt``:``Int`` = ``Int``(``energyFloat``)         ``'Is 120 now`

You can perform the following explicit conversions in Monkey:

| Source type | Target type | Notes |
| --- | --- | --- |
| Integer | Boolean | Result is true if source<>0, else false. |
| Floating point | Boolean | Result is true if source<>0.0, else false. |
| Array | Boolean | Result is true if source.Length<>0, else false. |
| Object | Boolean | Result is true if source<>Null, else false. |
| String | Boolean | Result is true if source<>"", else false. |
| String | Integer | Conversion is target dependant. |
| String | Floating point | Conversion is target dependant. |
| Base class object | Derived class object | Result is null if source is not a superclass of derived class. |

In some circumstances, Monkey will automatically perform an explicit conversion of a non-bool value to bool for you. This will occur when evaluating an expression for use with the If and While statements; the Until part of a Repeat loop; and when evaluating the arguments for the Not, Or and And operators. This allows you to use 'shortcut' code such as: If x Then y without the need to compare x with 0, "", [] or null.

### Boxing and unboxing conversions

A 'box' object is an object designed to contain a single primitive int, float or string value. The process of placing a value into a box object is known as 'boxing', while extracting a value from an object is known as 'unboxing'. To help with writing box objects, Monkey provides some simple features for boxing and unboxing values:

- An int, float or string value will be automatically converted to a new box object if that object provides a suitable New( Int ), New( Float ) or New( String ) constructor.
- An object will be automatically converted to an int, float or string value if that object provides a suitable To:Int(), ToFloat:Float() or ToString:String() method.

For example, here is a simple box class designed to hold an integer value:

`Class``IntBox``Field``value``:``Int``Method``New``( ``value``:``Int`` )``Self.value``=``value``End``Method``ToInt``:``Int``()``Return``value``End``End``Function``Main``()``Local``box``:``IntBox``box``=``10``Local``t``:``Int``=``box``Print``t``End`

## Statements

Program statements may only appear within method or function declarations.

A ; character may optionally appear after any statement, and multiple statements may be placed on the same source code line if separated by the ; character.

### If statement

The If statement allows you to conditionally execute a block of statements depending on the result of a series of boolean expressions.

The first boolean expression that evaluates to true will cause the associated block of statements to be executed. No further boolean expressions will be evaluated.

If no boolean expression evaluates to true, then the final else block will be executed if present.

The syntax for the If statement is:

If Expression [ Then ] Statements... ElseIf Expression [ Then ] Statements... Else Statements... EndIf

There may be any number of ElseIf blocks, or none. The final Else block is optional.

End or End If may be used instead of EndIf, and Else If may be used instead of ElseIf.

In addtion, a simple one line version of If is also supported:

If Expression [ Then ] Statement [ Else statement ]

### The Select statement

The Select statement allows you to execute a block of statements depending on a series of comparisons.

The first comparison to produce a match will cause the associated block of statements to be executed.

If no comparisons produce a match, then the final default block will be executed if present.

The syntax for the Select statement is:

Select Expression Case Expression [ , Expression... ] Statements... Default Statements... End [ Select ]

There may be any number of Case blocks, or none. The final Default block is optional. If the default block is present, it must appear after all Case blocks.

### While loop

The While loop allows you to execute a block of statements repeatedly while a boolean expression evaluates to true.

Note that a While loop may never actually execute any of it's statements if the expression evaluates to false when the loop is entered.

The syntax for the While loop is:

While Expression Statements... Wend

End or End While may be used instead of Wend.

Exit and Continue may be used within a While loop to abruptly terminate or continue loop execution.

### Repeat loop

Like the While loop, the Repeat loop also allows you to execute a block of statement repeatedly while a boolean expression evaluates to true.

However, unlike a While loop, a Repeat loop is guaranteed to execute at least once, as the boolean expression is not evaluated until the end of the loop.

The syntax for Repeat/Until loops is:

Repeat Statements... Until Expression

Or...

Repeat Statements... Forever

Exit and Continue may be used within a While loop to abruptly terminate or continue loop execution.

### Numeric For loop

A numeric For loop will continue executing until the value of a numeric index variable reaches an exit value.

The index variable is automatically updated every loop iteration by adding a constant step value.

The syntax for a numeric For loop is:

For [ Local ] IndexVariable = FirstValue To | Until LastValue [ Step StepValue ] Statements... Next

End or End For may be used instead of Next.

If present, Local will create a new local index variable that only exists for the duration of the loop. In addition, IndexVariable must include the variable type, or := must be used instead of = to implicitly set the variable's type.

If Local is not present, IndexVariable must be a valid, existing variable.

The use of To or Until determines whether LastValue should be inclusive or exclusive.

If To is used, the loop will exit once the index variable is greater than LastValue (or less than if StepValue is negative).

If Until is used, the loop will exit once the index variable is greater than or equal to LastValue (or less than or equal to if StepValue is negative).

If omitted, StepValue defaults to 1.

Exit and Continue may be used within a numeric For loop to abruptly terminate or continue loop execution.

### For EachIn loop

A For EachIn loop allows you to iterate through the elements of a collection.

A collection is either an array, a string, or a specially designed object.

The syntax for a For EachIn loop is:

For [ Local ] IndexVariable = EachIn Collection Statements... Next

End or End For may be used instead of Next.

If present, Local will create a new local index variable that only exists for the duration of the loop. In addition, IndexVariable must include the variable type, or := must be used instead of = to implicitly set the variable's type.

If Local is not present, IndexVariable must be a valid, existing variable.

If Collection is an array, the loop will iterate through each element of the array, and the type of the index variable must match the element type of the array.

If Collection is a string, the loop will iterate through each each character code of the string, and the type of the index variable must be numeric.

If Collection is an object, it must provide the following method:

`Method``ObjectEnumerator``:``Object``()`

The object returned by this method must itself provide the following methods:

`Method``HasNext``:``Bool``()``Method``NextObject``:``Object``()`

This allows you to build 'collection' style objects, such as the List and Map classes included in the standard Monkey modules that can be iterated through using For EachIn loops.

### Exit and Continue

Exit can be used within While, Repeat and For loops to abruptly exit the loop before the loop termination condition has been met.

Continue can be used within While, Repeat and For loops to force the loop to abruptly skip to the next loop iteration, skipping over any statements that may be remaining in the current loop iteration.

### Assignment statements

An assignment statement modifies a variable's value, and has the syntax:

VarExpression Operator Expression

Where VarExpression is an expression that evaluates to a variable, and Operator is one of the following:

= **=* /= Shl= Shr= Mod= += -= &= ~= |=

The = operator is used for plain assignment, while the remaining operators are used for update assignments.

### Expression statements

You may also use certain expressions as program statements. These are:

- Function or method call expressions.
- New expressions.

## Functions

A function is a self contained block of statements that can be called (or invoked) repeatedly from elsewhere in the program. Functions can also be passed parameters and return a result.

The syntax for declaring a function is:

Function Identifier : ReturnType ( Parameters ) Statements... End [ Function ]

For example:

`Function``Eat``:``Void``( ``amount``:``Int`` )``    ...``End`

Parameters is a comma separated sequence of function parameters:

Identifier : Type [ = InitExpression ]

Or...

Identifier := InitExpression

If you provide an InitExpression when declaring a function parameter, this means that the parameter has a default value and that the parameter can be optionally omitted when the function is called.

Once you have declared a function, it can be called with the syntax:

FunctionIdentifier ( Arguments )

where Arguments is a comma separated sequence of expressions.

For example:

`Function``Sum``:``Int``( ``x``:``Int``,``y``:``Int`` )``Return``x``+``y``End``Function``Main``()``Print``Sum``( ``10``,``20`` )``End`

Here is an example of using default parameters:

`Function``Sum``( ``x``:``Int``=``0``,``y``:``Int``=``0``,``z``:``Int``=``0`` )``Print``x``+``y``+``z``End``Function``Main``()``Print``Sum``()         ``'same as calling Sum( 0,0,0 )``Print``Sum``( ``10``,``20`` )  ``'same as calling Sum( 10,20,0 )``Print``Sum``( ``10``,,``30`` ) ``'same as calling Sum( 10,0,30 )``End`

### Function overloading

Functions can also be overloaded. This means that multiple declarations can share the same name, as long as they each have different parameters. Methods can be overloaded in exactly the same way as functions.

When a function is called, Monkey looks at the number and type of the parameters used in the call and looks for a matching overloaded version to use. For example:

`Function``Add``( ``value``:``Int`` )``End``Function``Add``( ``value``:``Float`` )``End``Function``Add``( ``value``:``String`` )``End``Function``Main``()``Add``( ``10`` )   ``'calls first version as 10 is of type Int``Add``( ``10.0`` ) ``'calls second version as 10.0 is of type Float``Add``( ``"10"`` ) ``'calls third version as "10" is of type String``End`

The number of parameters can also be used to differentiate between overloaded functions. For example:

`Function``Set``( ``x`` )``End``Function``Set``( ``x``, ``y`` )``End``Function``Main``()``Set``( ``10`` )    ``'calls first version``Set``( ``10``,``20`` ) ``'calls second version as it has two parameters``End`

When determining which overloaded version to actually use, Monkey uses the following logic:

- If an overloaded version is found that is an exact match for the number and type of function call parameters, that version is used. Note that if the function call involves the use of any default parameters, it is not considered an exact match.
- Otherwise, if there is exactly one overloaded version that can be called by implicitly converting the function call parameters, that version is used.
- Otherwise, an error is generated. In this case, you will need to manually cast some or all of the function call parameters to create an exact match.

For example:

`Function``Add``( ``value``:``Int`` )``End``Function``Add``( ``value``:``String`` )``End``Function``Main``()``Add``( ``10`` )   ``'OK, calls first version``Add``( ``"10"`` ) ``'OK, calls second version``Add``( ``10.0`` ) ``'error - unable to determine which version to call``End`

The error is caused by the fact that the function call parameter - '10.0' - is a floating point value and can therefore be implicitly converted to either an integer or a string, so Monkey cannot decide which overload to use.

To solve this problem, you would need to explicitly cast the parameter to either an integer or a string to give Monkey a 'hint' about which version you want used. For example:

`Add``( ``Int``(``10.0``) )        ``'Casts the float to an integer, calls first version`

## Methods

A Method is a function that is bound to a class. A method has implicit access to all members of its class, such as fields, globals and other methods and functions..

The syntax for declaring a method is similar to that for declaring a function:

Method Identifier : ReturnType ( Parameters ) [ Property ] Statements... End [ Method ]

Within a method you can also use the special Self and Super variables:

- Self may be used within a method to access the object the method is associated with.
- Super may be used within a method to call 'super class' methods.

The optional Property keyword can be used to declare a 'property method'.

A property method with 0 parameters can be invoked without any brackets. A property method with 1 parameter can be invoked be using it as the left-hand-side of an assignment statement, in which case the right-hand-side expression of the assignment is passed to the property method.

You can therefore create methods that behave like fields, but actually execute code when they are read or written. You can use method overloading to provide both read and write property methods, or provide just a read method, or even just a write method.

It is illegal to declare a property method with 2 or more parameters.

## Classes

A class is a kind of 'blueprint' for creating objects at runtime.

The syntax for declaring a class is:

Class Identifier [ < Parameters > ] [ Extends Class ] [ Implements Interfaces ] Declarations... End [ Class ]

Classes can contain field, method, constant, global and function declarations.

If no base class is specified using Extends, the class defaults to extending the built in Object class.

The Implements keyword is used to implement interfaces, and must be followed by a comma separated list of interface names. Please refer to the Interfaces section for more on interfaces.

A class is also a valid scope, and any constants, globals and functions declared within a class can be accessed outside of the class using the scope member access operator '.'. For example:

`Class``C``Global``T``End``Function``Main``()``C.T``=``10``End`

Once you have declared a class, you can create objects of that class at runtime using the New operator. For example:

`Class``MyClass``Field``x``,``y``,``z``End``Function``Main``()``Local``myObject``:=``New``MyClass``myObject.x``=``10``myObject.y``=``20``myObject.z``=``30``End`

### Constructors

Constructors are special methods that are called each time an object is created with New.

To declare a constructor, you simply declare a class method and name it New.

Constructors can take parameters and can be overloaded.

To invoke a super class constructor within a constructor, use the special Super variable.

## Generic classes

Generic classes allow you to write code that is not specific to a single data type.

A generic class is declared in a similar way to a normal class, only with an additional set of 'type parameters' enclosed within < and >.

For example:

`Class``Pointer``<``T``>``Method``Set``( ``data``:``T`` )``_data``=``data``End``Method``Get``:``T``()``Return``_data``End``Private``Field``_data``:``T``End`

Type parameters can be any valid identifier. Here, T is such a type parameter.

Within the declaration of a generic class, type parameters may be used anywhere a type is normally expected, for example, when declaring variables and function return types, and when creating new objects or arrays.

When it comes to actually using a generic class, you must provide actual types to be used in place of type parameters. Types parameters can be of any valid type, including int, float, string and array.

For example:

`Class``Actor``End``Function``Main``()``Local``pointer``:``Pointer``<``Actor``>``pointer``=``New``Pointer``<``Actor``>``pointer.Set``New``Actor``Local``actor``:=``pointer.Get``()``End`

The syntax Pointer indicates an 'instantiation' of the generic class Pointer.

This is in itself a unique class, so each time you use the Pointer class with a different type for T, you are actually creating a whole new class.

Generic classes are commonly used for writing container classes such as lists, stacks and so on, and the standard Monkey modules provide a set of simple generic container classes.

## Interfaces

An interface is similar to a class, except that it can only contain constants and abstract methods.

Classes can implement an interface using the Implements keyword in the class declaration.

Classes that implement an interface must declare each method declared in the interface.

An interface can be used where ever a class is expected, for example when declaring the types of variables, or function return types. An interface cannot however be used with New.

An Interface can also optionally extend existing interfaces, in which cases all methods in all extended interfaces must be declared by any implementing classes.

Interfaces can not be generic.

The syntax for declaring an interface is:

Interface Identifier [ Extends Interfaces ] Declarations... End [ Interface ]

All methods declared inside an interface are automatically treated as abstract, and can therefore have no 'body'.

Here is an example of using interfaces:

`Interface``Moveable``Method``Move``()``End``Interface``Drawable``Method``Draw``()``End``Class``Actor``Implements``Moveable``,``Drawable``Method``Move``()``Print``"Actor.Move()"``End``Method``Draw``()``Print``"Actor.Draw()"``End``End``Function``Move``( ``moveable``:``Moveable`` )``moveable.Move``End``Function``Draw``( ``drawable``:``Drawable`` )``drawable.Draw``End``Function``Main``()``Local``actor``:=``New``Actor``Move``actor``Draw``actor``End`

## Exceptions

Exceptions are special objects that can be 'thrown' to inform your program of unusual or abnormal behavior.

By placing code inside a 'try' block, you can catch thrown exceptions with a corresponding 'catch' block. For example...

`Function``Main``()``Try``Print``"Hello World!"``Throw``New``Throwable``Print``"Where am I?"``Catch``ex``:``Throwable``Print``"Caught a Throwable!"``End``End`

Try this with and without the throw statement.

Throw statements may appear anywhere in your application, not just inside a try block. When an object is thrown, it is thrown to the most recently executed try block capable of catching the object.

The class of objects used with throw and catch must extend the special built-in class Throwable. The Throwable class itself simply extends Object and provides no new methods or fields, so you may wish to extend Throwable to create your own exception classes with more functionality.

You can also catch multiple classes of exception object per try block, for example:

`Class``Ex1``Extends``Throwable``End``Class``Ex2``Extends``Throwable``End``Function``Main``()``For``Local``i``:=``1``To``10``Try``If`` (``i`` & ``1``) ``Throw``New``Ex1``Else``Throw``New``Ex2``Catch``ex``:``Ex1``Print``"Caught an ex1!"``Catch``ex``:``Ex2``Print``"Caught an ex2!"``End``Next``End`

When a try block has multiple catch blocks and an exception is thrown, the first catch block capable of handling the exception is executed. If no suitable catch block can be found, the exception is passed to the next most recently executed try block, and so on.

If no catch block can be found to catch an exception, a runtime error occurs and the application is terminated.

## Modules

A Monkey module corresponds to a single Monkey source file, and provides a named scope for the constants, globals, functions and classes declared in that file. Every Monkey source file declares a module, and every module has an associated source file.

The name of the module scope is the same as the name of the file (minus the directory path and file extension), so the names of Monkey source files must also be valid Monkey identifiers.

It is also strongly recommend that file/module names be completely lowercase - both to prevent any issues with cased/uncased filesystems and to provide consistency with the standard module set.

One module may import another using the import statement. All import statements must appear at the top of a module before any declarations. The syntax for an import statement is:

Import ModulePath

Where ModulePath describes the file location of the Monkey module to import. This must be a sequence of 'dot' separated identifiers, and is treated as a relative filesystem path with dots representing directory separators. The last component in the path represents either an actual .monkey source file, or a directory containing a .monkey source file of the same name.

Given a module's relative path, Monkey will look for an actual module to import in the following locations (and in this order):

- The current directory - ie: the directory the importing file is in.
- The project directory - ie: the directory the main source file is in. This is the source file that was passed to the 'trans' compiler, and that contains the declaration for Main().
- The modules directory - ie: the directory named 'modules' in the Monkey distribution.

For example, given the following import directive:

`Import``myutil.mycolor`

Monkey will first look for the files myutil/mycolor.monkey and myutil/mycolor/mycolor.monkey in the current directory.

(Note: the reason modules are allowed to be represented as either a single .monkey file, or as a .monkey file within a directory of the same name is for pure convenience. Sometimes it's more convenient for a module to consist of a single file, while sometimes it's more convenient for a module to have its own directory.)

If either is found, it is imported into the current module and the search ends.

If both are found, an error is generated.

If neither is found the search continues with the project directory and, failing that, the modules directory.

If the module is not found anywhere, an error is generated.

Once successfully imported, the importing module can access the declarations made in the imported module, by using the imported module's name as a scope.

Here is a simple import example:

`'----- file1.monkey -----``Import``file2``'after this, file2 can be used as a scope``Function``Main``()``Print``file2.X``'access global X in file2 module``file2.Test``'access function Test in file2 module``End``'---- file2.monkey ----``Global``X``:=``1``Function``Test``()``Print``"file2.Test"``End`

When accessing identifiers in imported modules, Monkey allows you to omit the module scope as long as there are no 'clashes' between identifiers in multiple modules. For example:

`'----- file1.monkey ----``Import``file2``Import``file3``Function``Main``()``Print``X``'OK, accesses file2.X``Print``Y``'OK, accesses file3.Y``Test``'ERROR! Which Test? file2.Test or file3.Test?``file2.Test``'OK, I now know which module to get Test from``End``'----- file2.monkey -----``Global``X``:=``1``Function``Test``()``Print``"file2.Test"``End``'----- file3.monkey -----``Global``Y``:=``2``Function``Test``()``Print``"file3.Test"``End`

By default, any imports made by a module are automatically made available to importers of that module. That is, if module X imports module Y, and module Y imports module Z, the result is that module X effectively imports module Z.

However, if an import is declared to be private, that import is NOT made available. For example:

`'----- file1.monkey -----``Import``file2``Function``Main``()``Print``X``'OK, accesses file2.X``Print``Y``'OK, accesses file3.Y``Print``Z``'ERROR! can't see file.Z``End``'----- file2.monkey -----``Import``file3``'Public import: When you import file2, you also import file3``Private``Import``file4``'Private - ie: internal use only. Only file2 can access file4. file1 cannot access file4.``Public``Global``X``:=``1``'----- file3.monkey -----``Global``Y``:=``2``'----- file4.monkey -----``Global``Z``:=``3`

Modules can be stored in a directory hierarchy and imported using a 'dotted' module path, for example:

`'----- file1.monkey -----``Import``file2``Import``util.file3``Function``Main``()``Print``file2.X``Print``file3.Y``End``'----- util/file2.monkey ----``Global``X``:=``1``'----- util/file3.monkey -----``Global``Y``:=``2`

Note that the directory path (in this case, 'util') is not used in any way except to locate the module. The module name is still just 'file3' - not 'util.file3'.

### The Alias directive

The Alias directive allows you to assign a local name to a constant, global, function or class declared in another module. This can be used to create 'shortcuts' for clashing identifiers.

The syntax for Alias is:

Alias Identifier = ModulePath . Identifier

Alias directives must appear in the 'import' section of a module, before any code.

For example:

`'----- file1.monkey -----``Import``file2``Import``file3``Alias``T``=``file2.T``'which 'T' to use``Function``Main``()``Print``T``'Prints '1'``End``'----- file2.monkey -----``Global``T``:=``1``'----- file3.monkey -----``Global``T``:=``2`

## Public and Private

The Public and Private directives are used to control the visibility of subsequent declarations in a module or class.

If the Public directive is used in the main body of a module, all subsequent declarations will be public, and will be visible outside of the current module.

If the Private directive is used in the main body of a module, all subsequent declarations will be private and will not be visible outside of the current module.

For example:

`Private``Global``x``,``y``,``z``'These are private to the current module``Public``Global``P``,``Q``,``R``'These can be used by any module`

When used inside a class declaration, Public and Private work in a similar way to control the visibility of subsequent member declarations. For example:

`Class``MyClass``Private``Field``x``,``y``,``z``'these are NOT visible outside of this module.``Public``Field``P``,``Q``,``R``'these ARE visible outside of this module.``End`

Note that private class members are not private to the class, but to the entire module. This means that code outside of the class but within the same module can still access class private members.

## External declarations

The Extern directive is used to connect Monkey code to non-Monkey code. It lets you mix Monkey code (to be translated into the target platform language) with native target platform code.

When the Extern directive is used in the main body of a module, all subsequent global, function and class declarations will be treated as external declarations.

External declarations are assumed to be implemented elsewhere in native code, and as such may not contain a 'body'.

In the case of external global variables, this means the global may not be initialized - it is assumed to be initialized by native code.

In the case of external functions, this means the function may not contain any code, and must not be terminated with an End directive.

In the case of external classes, this means any globals or methods declared in the class may not contain a 'body' either.

External declarations may however be assigned a 'symbol' in the form of a string literal. This is the native symbol to be used by the Monkey translator when the declaration is referenced by Monkey code.

By default, external declarations are public. You can use Extern Private to prevent external declarations from being visible outside the current module.

Here are some examples of using extern:

`Extern``Global``ActiveDriver``:``Driver``=``"xyzActiveDriver"``'Native name of this global is xyzActiveDriver``Class``Driver``=``"xyzDriver"``'The native name of this class is 'xyzDriver'.``Method``Method1``()       ``'By default, native name is same as declaration name - Method1 here.``Method``Method2``()       ``'native name is Method2``End``Public``'return to public declarations`

## Memory Management

Monkey is a garbage collected language, and depends on the underlying target language to provide memory management.

Finalizers are not supported. If you need an object to be 'destroyable', you will need to add a 'Destroy' type method.

The garbage collector is capable of collecting cyclic data structures such as linked lists automatically.

The current C++ garbage collector will only collect garbage when control is returned to the OS. In the case of C++ Mojo targets such as IOS and GLFW, this occurs after any of the 'On' methods such as OnCreate, OnUpdate etc return.

In general, the best way to use the garbage collector is to ignore it! Although such practices as 'nulling out' object references are common, they are seldom required.

But it's a good idea to monitor your apps memory requirements as you develop anyway. This will allow you to catch any memory issues, GC related or otherwise, early on.

## The preprocessor

Monkey contains a very simple built-in preprocessor based on the syntax of the Monkey If statement that allows you to enable or disable blocks of code from being generated or translated, based on certain conditions.

The following preprocessor directives are supported:

#If #ElseIf #Else #End #Rem #Print #Error

Preprocessor directives must appear at the start of a line, and may be preceded by optional whitespace.

The #If and #Else If directives must be followed by a constant Monkey expression. If this expression evaluates to true, then code generation is enabled, otherwise it is disabled.

The following built in constants may be used in preprocessor expressions:

| Constant | Description |
| --- | --- |
| HOST | Host operatintg system, one of: winnt macos linux |
| LANG | Target language, one of: js as cs cpp java |
| TARGET | Target system, one of: ios android winrt glfw html5 flash xna psm |
| CONFIG | Target build config, one of: debug release |
| CD | Directory of source file being built |
| MODPATH | Module being built |

The #Rem directive is exactly the same as #If False - it unconditionally disables code generation. Note that this allows 'block rems' to be 'nested'.

8. How to create a global method in C# that can be called without prefixing the classname?
   URL: https://stackoverflow.com/questions/22771671/how-to-create-a-global-method-in-c-that-can-be-called-without-prefixing-the-cla
   # How to create a global method in C# that can be called without prefixing the classname?

- Tags: c#, .net, function, static
- Score: 0
- Views: 1,574
- Answers: 4
- Asked by: Maestro (9,894 rep)
- Asked on: Mar 31, 2014
- Last active: Apr 3, 2014
- License: CC BY-SA 3.0

---

## Question

If I want to make a function that can be called from every location in my project, I create static class with a static function, but I still have to refer to the function as `Class.Method` instead of `Method` even if I import the static class with `using`. How can you do this?

---

## Answer 1 — Score: 6

- By: Servy (203,836 rep)
- Answered on: Mar 31, 2014

You cannot. Functions must be declared within a type in C#.

---

## Accepted Answer — Score: 2

- By: Marc Gravell (1,072,351 rep)
- Answered on: Apr 3, 2014

At the Build 2014 keynote it was announce that the following should work in the next version:

```
using Class;

...

Method(...);
```

Basically, exactly what you wanted. The `using Class;` imports the static methods from the `Class` type so that they don't need to be referenced from the type.

---

## Answer 3 — Score: 0

- By: T McKeown (12,886 rep)
- Answered on: Mar 31, 2014

You have to refer to the **STATIC** method as Class.Method() unless you are inside the class.

---

## Answer 4 — Score: 0

- By: Michał (2,282 rep)
- Answered on: Mar 31, 2014

First of all - you cannot import a static class. You only import a `namespace` in which it is contained.

You actually cannot do it - that is the basic principle of OOP - everything has it's class. Methods in `static class`es are the replacement for the global functions in C++

9. Reflection on constructors..  How to access method of new variant? – Monkey 2
   URL: https://www.monkeycoder.co.nz/forums/topic/reflection-on-constructors-how-to-access-method-of-new-variant/
   Reflection on constructors.. How to access method of new variant? – Monkey 2

About Monkey 2› Forums› Monkey 2 Programming Help› Reflection on constructors.. How to access method of new variant?

This topic contains 4 replies, has 2 voices, and was last updated by jondecker76 1 day, 21 hours ago.

Viewing 5 posts - 1 through 5 (of 5 total)

Author

Posts

January 22, 2019 at 1:17 am#15986

Participant

I’m finally to the point where I can create new class instances using reflection…

However, I’m stuck, as now I can’t do anything with the new variant. The variant.DyanmicType property does indeed report that I’ve created the class that I want. However, I can’t access anything within the class from this point, as I then get an error about the variant not having the property or method…

Simple sample:

Monkey

Class A Method Test() Print "Success!" End End Class B Field a:Variant End Function Main() Local instance:=New B instance.a=New A instance.a.Test() ' Fails, because Value of type 'monkey.types.Variant' has no member named 'Test' End

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

Class A

Method Test()

Print "Success!"

End

End

Class B

Field a:Variant

End

Function Main()

Local instance:=New B

instance.a=New A

instance.a.Test() ' Fails, because Value of type 'monkey.types.Variant' has no member named 'Test'

End

0

January 22, 2019 at 6:03 am#15988

Participant

You can store any Object in a Variant, and because of that you have to tell Monkey2 what it is.

With casting you can tell Monkey2 that instance.a is an instance of class A:

Monkey

[crayon-5c4966e1f17e0068666388 inline="true" ] Class A Method Test() Print "Success!" End End Class B Field a:Variant End Function Main() Local instance:=New B instance.a=New A Cast (instance.a).Test() End

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

[crayon-5c4966e1f17e0068666388 inline="true" ]

Class A

Method Test()

Print "Success!"

End

End

Class B

Field a:Variant

End

Function Main()

Local instance:=New B

instance.a=New A

Cast (instance.a).Test()

End

[/crayon]

Using that way you could use different classes that implement the same methods:

Monkey

[crayon-5c4966e1f17e6071418242 inline="true" ] Interface ITest Method Test() End Class A Implements ITest Method Test() Print "Success A!" End End Class B Implements ITest Method Test() Print "Success B!" End End Class C Implements ITest Method Test() Print "Success C!" End End Class TheClass Field a:Variant End Function Main() Local instance:=New TheClass instance.a=New A Cast (instance.a).Test() instance.a=New B Cast (instance.a).Test() instance.a=New C Cast (instance.a).Test() End

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

[crayon-5c4966e1f17e6071418242 inline="true" ]

Interface ITest

Method Test()

End

Class A Implements ITest

Method Test()

Print "Success A!"

End

End

Class B Implements ITest

Method Test()

Print "Success B!"

End

End

Class C Implements ITest

Method Test()

Print "Success C!"

End

End

Class TheClass

Field a:Variant

End

Function Main()

Local instance:=New TheClass

instance.a=New A

Cast (instance.a).Test()

instance.a=New B

Cast (instance.a).Test()

instance.a=New C

Cast (instance.a).Test()

End

[/crayon]

0

January 22, 2019 at 6:48 am#15990

Participant

Thanks for the reply.

I was afraid of that. It seems like there is no way to get a true object from the reflection system and have it usable as a normal object (without heaping up piles of GetType..GetDecl..Invoke..Cast.. and making the code overly complex)

I’m trying to build an XML parser that builds objects out of “skeleton” classes from the XML data. But I wanted to do so without special cases and Casts, as there are literally hundreds of skeleton classes. I just can’t find a way to build a true object from it’s name:String in monkey2. I’m guessing that I’m just going to have to bite the bullet and write a custom loader for each and every one of the hundreds of object types. Bummer

For example, I just need to make a function that:

instance:=ObjectFromName(“class_name”)

0

January 22, 2019 at 7:18 am#15991

Participant

Could you use the following? instance:=ObjectFromName<class_name>(“class_name”)

Creating an object just from a string, without telling Monkey2 what it is, is probably very hard if possible at all.

0

January 22, 2019 at 10:17 am#15994

Participant

I’m going to take a hybrid approach – I’ll have to make routines to match the appropriate skeleton class to the XMLString – but then I’ll use reflection to fill in the fields in the class. At least I’m hoping this method will work

0

Author

Posts

Viewing 5 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic.

10. Monkey Documentation
   URL: http://regal-internet-brothers.github.io/monkey/docs/Modules_reflection_ClassInfo.html
   Monkey Documentation

# Class ClassInfo

ClassInfo objects describe classes declared by your program and in modules. More...

---

| Properties: | Attributes : Int () ElementType : ClassInfo () Interfaces : ClassInfo[] () Name : String () SuperClass : ClassInfo () |
| --- | --- |
| Methods: | ArrayLength: Int ( inst:Object ) ExtendsClass: Bool ( clas:ClassInfo ) GetConst: ConstInfo ( name:String, recursive:Bool ) GetConstructor: FunctionInfo ( argTypes:ClassInfo[] ) GetConstructors: FunctionInfo[] () GetConsts: ConstInfo[] ( recursive:Bool ) GetElement: Object ( inst:Object, index:Int ) GetField: FieldInfo ( name:String, recursive:Bool ) GetFields: FieldInfo[] ( recursive:Bool ) GetFunction: FunctionInfo ( name:String, argTypes:ClassInfo[], recursive:Bool ) GetFunctions: FunctionInfo[] ( recursive:Bool ) GetGlobal: GlobalInfo ( name:String, recursive:Bool ) GetGlobals: GlobalInfo[] ( recursive:Bool ) GetMethod: MethodInfo ( name:String, argTypes:ClassInfo[], recursive:Bool ) GetMethods: MethodInfo[] ( recursive:Bool ) NewArray: Object ( length:Int ) NewInstance: Object () SetElement: Void ( inst:Object, index:Int, value:Object ) |

## Detailed Discussion

ClassInfo objects describe classes declared by your program and in modules.

The ArrayLength, GetElement, SetElement and NewArray methods are only valid if the class represents an array box class. You can determine whether a class is an array box class with the ElementType method. If ElementType returns non-null, then the class is an array box class.

The recursive parameter of the GetConst, GetGlobal, GetField, GetMethod and GetFunction methods indicates whether or not the entire class hierarchy should be searched, or only the current class.

The recursive parameter of the GetConsts, GetGlobals, GetFields, GetMethods and GetFunctions methods indicates whether or not all declarations spanning the entire class hierarchy should be returned, or only those declared within the current class.

---

## Property Documentation

Method Attributes : Int () Property

Get class attributes.

Method ElementType : ClassInfo() Property

Get array element type.

Method Interfaces : ClassInfo [] () Property

Get interfaces implemented by this class, or interfaces extended by this interface.

Method Name : String () Property

Get name of class.

Method SuperClass : ClassInfo() Property

Get super class of class.

---

## Method Documentation

Method ArrayLength : Int ( inst:Object )

Get length of an array.

Method ExtendsClass : Bool ( clas: ClassInfo)

Check if class extends another class, or implements an interface.

Method GetConst : ConstInfo( name:String, recursive:Bool )

Get a class const.

Method GetConstructor : FunctionInfo( argTypes: ClassInfo [] )

Get a class constructor.

Method GetConstructors : FunctionInfo [] ()

Get all constructors declared by class.

Method GetConsts : ConstInfo [] ( recursive:Bool )

Get all consts declared by class.

Method GetElement : Object ( inst:Object, index:Int )

Get an array element.

Method GetField : FieldInfo( name:String, recursive:Bool )

Get a class field.

Method GetFields : FieldInfo [] ( recursive:Bool )

Get all fields declared by class.

Method GetFunction : FunctionInfo( name:String, argTypes: ClassInfo [], recursive:Bool )

Get a class function.

Method GetFunctions : FunctionInfo [] ( recursive:Bool )

Get all functions declared by class.

Method GetGlobal : GlobalInfo( name:String, recursive:Bool )

Get a class global.

Method GetGlobals : GlobalInfo [] ( recursive:Bool )

Get all globals declared by class.

Method GetMethod : MethodInfo( name:String, argTypes: ClassInfo [], recursive:Bool )

Get a class method.

Method GetMethods : MethodInfo [] ( recursive:Bool )

Get all methods declared by class.

Method NewArray : Object ( length:Int )

Create a new array box object of this class.

Method NewInstance : Object ()

Create a new object of this class.

Method SetElement : Void ( inst:Object, index:Int, value:Object )

Set an array element.

---

Monkey Documentation

Reflection is in! – Monkey 2

Call an object method - Rosetta Code

Monkey Documentation

Monkey Documentation