Can I overload methods with different parameterised types in EK9?

← Generics · Ref: Q655

Because EK9 creates independent types for each parameterisation (no erasure), you can overload methods with different parameterised types. This is impossible in Java due to type erasure.

OVERLOADING WORKS (METHODS)

Because List of Integer and List of String are distinct types, a class can declare both:

  Counter
    count()
      -> items as List of Integer
      <- rtn as Integer: length items
    count()
      -> items as List of String
      <- rtn as Integer: length items

Both signatures coexist without ambiguity.

FUNCTIONS CANNOT BE OVERLOADED

Module level functions cannot share a name whatever their parameters - two functions called process is E01030 (duplicate name). Give functions distinct names (sumIntegers, joinStrings).

WHY JAVA CANNOT

Java erases generics at runtime: both List<Integer> and List<String> become List. Two methods with the same erased signature conflict.

AMBIGUITY DETECTION (E06140)

EK9 still detects GENUINE ambiguity. If two overloads match equally well, E06140 is raised. This happens with coercion costs, not with distinct parameterised types.

DISTINCT TYPE ARGUMENTS

Overloading methods with different type arguments is always unambiguous: a class may declare handler(opt as Optional of String) and handler(opt as Optional of Integer) side by side.
The compiler resolves the correct overload from the argument type.

See Q653 for type independence. See Q196 for multi-parameter generics. See Q194 for generic class basics.

Example

defines module qa.genericsdeep.methodoverloading

  defines function

    <?-
      Module level FUNCTIONS cannot be overloaded at all (two functions with the same name are E01030
      whatever their parameters), so these have different names. Overloading by parameterised type
      is done with METHODS on a class - see Counter below.
    -?>
    sumIntegers()
      -> items as List of Integer
      <- rtn as Integer: 0
      for item in items
        rtn += item

    joinStrings()
      -> items as List of String
      <- rtn as String: ""
      for item in items
        rtn += item


  defines class

    <?-
      Methods accepting different parameterised types.
      Each List parameterisation is an independent type,
      so these are unambiguous overloads (unlike Java with erasure).
    -?>
    Counter

      count() as pure
        -> items as List of Integer
        <- rtn as Integer: length items

      count() as pure
        -> items as List of String
        <- rtn as Integer: length items

  defines program

    MethodOverloadingDemo()
      stdout <- Stdout()

      // === INTEGER LIST ===

      numbers <- List() of Integer
      numbers += 10
      numbers += 20
      numbers += 30
      intSum <- sumIntegers(numbers)
      stdout.println(`Integer sum: ${intSum}`)

      // === STRING LIST ===

      words <- List() of String
      words += "hello"
      words += " "
      words += "world"
      joined <- joinStrings(words)
      stdout.println(`Joined: ${joined}`)

      // === OVERLOADED METHODS FOR DIFFERENT LIST TYPES ===

      counter <- Counter()
      intCount <- counter.count(numbers)
      stdout.println(`Integer count: ${intCount}`)

      strCount <- counter.count(words)
      stdout.println(`String count: ${strCount}`)

Common mistakes

E01030 — E01030 is a duplicate-name error: module level functions cannot be overloaded, so a second function with the same name is rejected whatever its parameter types. Give each function its own name, or use methods on a class when you want overloads by parameterised type. See ek9 -h E01030 for details.

Incorrect:

sumIntegers()
      -> items as List of Integer
      <- rtn as Integer: 0
    sumIntegers()
      -> items as List of Integer
      <- rtn as Integer: 0

Correct:

sumIntegers()
      -> items as List of Integer
      <- rtn as Integer: 0
Other ways to ask this
  • Does EK9 allow method overloading with generics unlike Java?
  • What is E06140 ambiguous method match?
  • How do independent generic types enable overloading?

Coming from another language?

Java: cannot overload methods with different generic parameterisations (erasure). C++: can overload with different template instantiations. Rust: no method overloading (uses traits instead). Go: no method overloading. Kotlin: same erasure limitation as Java. EK9: full overloading with distinct parameterised types because no erasure.

Keywords: ambiguity, method, migrate, distinct, parameterised, generic, E06140, type-parameter, overload, erasure