Fremde Java-Klassen erweitern mit Manifold: Extensions

In den letzten Artikeln hatten wir bereits über die mannigfaltigen Möglichkeiten Manifolds geschrieben. Neben einem kurzen Artikel zu den Grundlagen von Manifold hatten wir gezeigt, mit wie wenig Aufwand sich JSON-Schnittstellen über Manifold integrieren ließen. Ein anderes interessantes Feature von Manifold ist das Erweitern fremder Klassen mit eigenen Methoden und wird in diesem Artikel beschrieben.

Wäre es nicht spannend, wenn man einfach so den bestehenden Klassen der Java Platform API neue Methoden hinzufügen könnte, damit man sich die eigenen Util-Klassen sparen kann? So wollen wir nun einmal das im ersten Artikel dieser Serie genannte Beispiel implementieren, bei dem die Klasse java.lang.String aus der Java Platform API eine revert()-Methode bekommen soll.

Dazu legen wir eine Klasse StringExtension an. Diese muss sich im Package extensions.java.lang.String befinden, da sie der Klasse java.lang.String eine Methode hinzufügen soll. Der Inhalt der Klasse lautet:

package extensions.java.lang.String;

import manifold.ext.api.Extension;
import manifold.ext.api.This;

@Extension
public class StringExtension {
    public static String revert( @This String thiz) {
        return new StringBuilder(thiz).reverse().toString();
    }
}

Wir annotieren die Klasse also mit @Extension, um Manifold zu signalisieren, dass es sich hierbei um eine Klasse mit Extension Methods handelt. Dann legen wir eine statische Methode revert() an, welche als Parameter einen String erhält, der mit @This annotiert ist. Dies sorgt dafür, dass Manifold die revert()-Methode tatsächlich als Instanzmethode der Klasse String hinzufügt. Die Methode dreht den String um und gibt ihn zurück.

Nun können wir in unserem Java-Programm das Folgende machen:

String test = "Hello World!";
System.out.println(test.revert());

Wir haben der Klasse String aus der Java Platform API also tatsächlich unsere revert()-Methode untergejubelt! Das Resultat:

!dlroW olleH

Mit diesem Konzept können wir für beliebige Klassen aus der Java Platform API oder aus fremden Bibliotheken einfache Methoden für unser Programm hinzufügen und sparen uns damit unübersichtliche Util-Klassen.

Was übrigens nicht funktioniert, ist hiermit eine bereits bestehende Methode zu überschreiben. Wenn wir etwa folgendes versuchen:

@Extension
public class StringExtension {
    public static int length(@This String thiz) {
        return -1;
    }
}

bekommen wir einen Fehler:

Error:java: method length() is already defined in class java.lang.String

Was dagegen funktioniert, ist eine Überladung:

    public static int length(@This String thiz, boolean val) {
        return -1;
    }

Der aufrufende Code, der zunächst die originale und anschließend die überladene Methode aufruft:

String test = "Hello World!";
System.out.println("Length: " + test.length());
System.out.println("Length overloaded: " + test.length(true));

Die Ausgabe nach dem Ausführen:

Length: 12
Length overloaded: -1

Mit dem Extension-System von Manifold kann man fremde Klassen also einfach nachträglich “ergänzen”. Während das Überschreiben von Methoden verboten ist, ist die Überladung durchaus möglich.

Short URL for this post: https://wp.me/p4nxik-3kJ
Steffen Jacobs

About Steffen Jacobs

Java Consultant & Developer at Orientation in Objects GmbH. Follow me on Twitter and find me on LinkedIn and Xing. Some of the source code associated with the blog articles can be found on GitHub.
This entry was posted in Java and Quality and tagged , , . Bookmark the permalink.

Leave a Reply