Types and OOP Generics

# Generics

Generics let Klyn preserve strong typing across reusable containers and abstractions. They are central to the collection APIs and to user-defined types that must carry a caller-chosen element type.

Generic Type Parameters

    public interface Collection<T = Double>:
        public add(item as T) as Void

Generic parameters appear between angle brackets and can be referenced throughout the type body.

Instantiating Generic Types

    import klyn.collections

    names = ArrayList<String>()
    scores = Map<String, Int>()

Explicit type arguments are especially valuable when the initial state is empty and therefore cannot drive inference on its own.

Default Generic Arguments

    public class NDArray<T extends AbstractNumber = Double>:
        pass

Defaults let a generic API stay concise when one concrete type is overwhelmingly common.

Constraints

    public class NDArray<T extends AbstractNumber = Double>:
        pass

A constraint restricts which types may be substituted for the generic parameter.

Inference from Literal Content

    import klyn.collections

    [10, 20, 30]                  # ArrayList<Int>
    s:[10, 20, 30]                # ArrayListSync<Int>
    f:[10, 20, 30]                 # Array<Int>
    fs:[10, 20, 30]                # ArraySync<Int>
    i:[10, 20, 30]                 # ImmutableList<Int>
    l:[10, 20, 30]                 # LinkedList<Int>
    ls:[10, 20, 30]                # LinkedListSync<Int>
    {"a": 1, "b": 2}              # HashMap<String, Int>
    (1, 2, 3)                     # Tuple<Int, Int, Int>

Literal inference removes boilerplate, but explicit annotations remain the better choice when the surrounding API should communicate a stable type contract. Collection prefixes are part of that contract: they select the concrete collection generated by the compiler, not a late runtime conversion.

Klyn now separates immutable homogeneous sequences from tuples: `ImmutableList<T>` is exposed through `IList<T>`, while `Tuple<...Ts>` is positional and heterogeneous.

Generic Types and Reflection

    import klyn.collections

    metadata = type(List<Int>)
    print(metadata.isGenericInstantiation)
    print(metadata.genericParameterCount)

Generic instantiations are visible through reflection, which is useful for tooling and typed framework code.