Evo API Draft
  • Java
    • Intro
    • Imports
    • Constructing Objects
    • Properties
    • Type Annotations
    • Conversions
    • Explicit Conversions
    • Behaviors
    • Creating and Extending Types
    • Promises
  • mc-std
    • Intro
    • Commands
Powered by GitBook
On this page
  1. Java

Creating and Extending Types

Creating and extending Java types: the key feature.

Perhaps one of the most important features of Evo is the ability to create and extend Java classes. You can use Java.create for this.

Let's say we want to make our own Runnable implementation. Runnable is an interface, so it doesn't have its own constructor. That means we have to make one.

We'll create a PrintRunnable. It takes in a Java String, and we'll print that string once it is run.

let PrintRunnable = Java.create([ Runnable ], class {
    [Java.construct] = [ String ];
    
    constructor(text: String) {
        this.text = text;
    }
    
    run() {
        console.log(this.text);
    }
});

Now, let's break this down. The first argument, [ Runnable ] is a list of all types we're inheriting from: one class (optionally), and as many interfaces as we want.

Then, in the anonymous class we create, we define a property called [Java.constructor] (This is a JS symbol, so it doesn't clutter the class property namespace.) We only have one constructor, and that constructor just takes in one argument. However, we can also do multiple constructors:

[Java.constructor] = [
    Constructor([ String ]),
    Constructor([ String, Integer ])
];

Our constructor is just as normal, except it takes in a Java String, not a JS String. Arguments aren't converted if they're parameters in a Java.create class, although you can convert them manually using Java.fromJava and Java.toJava.

What if I want to add my own new method, though? You still can, you just have to specify types yourself. The last type is treated as the return type.

let PrintRunnable = Java.create([ Runnable ], class {
    [Java.methods] = {
        // Alternatively, instead of `Method`, we could do `Java.method`
        // But that's kind of ugly, I don't know if we should do that
        runForFriend: Method([ String ], Void)
    };

    [Java.construct] = Constructor([ String ]);
    
    [Java.properties] = {
        text: String
    };
    
    constructor(text: String) {
        this.text = text;
    }
    
    run() {
        console.log(this.text);
    }
    
    runForFriend(friend: String) {
        console.log(`No problem, ${friend}! ${this.text}`);
    }
});

It should also be noted that you can just do this:

let MyJavaClass = Java.create(class { 
    ... 
});

If you have nothing to inherit from.

On the other hand, if you want to create an interface, you can use the Java.impl.

let LoggedRunnable = Java.impl({
    [Java.methods] = {
        text: Method(String)
    }
    
    run() {
        console.log(this.text());
    }
});
PreviousBehaviorsNextPromises

Last updated 2 years ago