Extensions

Some modern programming language have the concept to extend an existing class with new functions over a extension struct without updating the used library. As example Kotlin has these functionality build in. It helps to order the code without the usage of new class construct. Also Dart has this concept to create extension functions for existing classes.

Before you start the usage of them, you need to know which class do you want to extend. Otherwise there is no really usage for that specific language feature.

The reduce complexity with the given `FunctionSpec` it contains a dedicated variant only for extensions.

Extension creation

The creation of an extension function is not very complex:

val extension = ExtensionSpec.builder("TestExtension", "String")
    .function {
        FunctionSpec.builder("hasSize")
            .returns(Boolean::class)
            .addCode(
                CodeBlock.of(
                    "return this.length > 2;"
                )
            )
            .build()
    }
    .build()

The snippet above creates an extension class for the given `String` class from the Dart programming language. This class contains an additional method which checks, if a string has a greater size than two.

extension TestExtension on String {
    bool hasSize() {
        return this.length > 2;
    }
}

Generic extensions

An extension can also be added to a generic class like `List, Maps etc.` also to own created classes. The generic type is bound on the static type of the structure that the method calls. So it's not possible to create a generic function in a non-generic class.

Let's create an extension for the List class from Dart:

val genericExtension = ExtensionSpec.builder("ListExt", List::class.parameterizedBy(ClassName("T")))
    .genericTypes(ClassName("T"))
    .build()

Which results in this generated class:

extension ListExt<T> on List<T> {}

The extension structure checks if the generic types are used correctly otherwise it throws an exception.

Unnamed extensions

The declaration of an extension typically involves assigning a name. Unnamed extensions, on the other hand, lack a specific identifier and are only visible within the library where they are declared. Since they are not applied explicitly, unnamed extensions cannot be utilized to resolve API conflicts.

Add example here

Last updated