## Syntactic and semantic differences between Java and the generated Dart bindings

This document highlights the key syntactic and semantic variations between Java
and Dart and how JNIgen addresses them to ensure smooth interoperability.

### Method overloading

Java supports overloading methods. This means that it can distinguish between
two methods with the same name that have a different signature.

```java
// Java
public class Calculator {
  public int add(int a, int b) {
    return a + b;
  }

  public double add(double a, double b) {
    return a + b;
  }

  public float add(float a, float b) {
    return a + b;
  }
}
```

This is not the case for Dart. Each method of a class must have a unique name.
To overcome this limitation, JNIgen adds a dollar sign (`$`) and a numeric
suffix to the end of the overloaded method name.

```dart
// Dart Bindings - Boilerplate omitted for clarity.
class Calculator extends JObject {
  int add(int a, int b) { /* ... */ }

  double add$1(double a, double b) { /* ... */ }

  double add$2(double a, double b) { /* ... */ }
}
```

> [!WARNING]  
> Running the code generator again on a different version of the library can map
> the methods differently if the order of the methods change or another
> overloading of the same method gets added.
>
> Double check the doc comments on the generated methods to make sure you are
> calling your intended method.

You might wonder why the method isn't renamed to `add1` instead of `add$1`. The
reason is that a method named `add1` could already exist in the Java class. On
the other hand, Java identifiers normally do not contain dollar signs.

> [!NOTE]  
> See
> [Identifiers containing dollar signs](#identifiers-containing-dollar-signs) to
> see what JNIgen does when identifiers contain dollar signs.

```java
// Java
public class Calculator {
  public int add(int a, int b) {
    return a + b;
  }

  public double add(double a, double b) {
    return a + b;
  }

  public float add(float a, float b) {
    return a + b;
  }

  public int add1(int a) {
    return a + 1;
  }

  public double add1(double a) {
    return a + 1;
  }
}
```

In this case, the generated code will be:

```dart
// Dart Bindings - Boilerplate omitted for clarity.
class Calculator extends JObject {
  int add(int a, int b) { /* ... */ }

  double add$1(double a, double b) { /* ... */ }

  double add$2(double a, double b) { /* ... */ }

  int add1(int a) { /* ... */ }

  double add1$1(double a) { /* ... */ }
}
```

### Fields and methods with the same name

In Java, we can have a field and a method with the same name. This is not
possible in Dart.

```java
// Java
public class Player {
  // Player's personal duck!
  public Duck duck;

  // Lower your head!
  public void duck() { /* ... */ }
}
```

JNIgen handles this similarly to [method overloading](#method-overloading). The
method with the same name as the field will be appended by a dollar sign (`$`)
followed by a numeric suffix.

```dart
// Dart Bindings - Boilerplate omitted for clarity.
class Player extends JObject {
  Duck get duck { /* ... */ };
  set duck(Duck value) { /* ... */ }

  void duck$1() { /* ... */ }

  // If there were more `duck` methods they would be named
  // `duck$2`, `duck$3`, ...
}
```

It is important to note that the order of renaming is fields-first
methods-second. So when both a field named `duck` and a method named `duck`
exist, the field keeps its original name as seen above.

However the renaming happens for superclasses first. Consider this case.

```java
// Java
public class Player {
  // Lower your head!
  public void duck() { /* ... */ }
}

public class DuckOwningPlayer extends Player {
  // Player's personal duck!
  public Duck duck;
}
```

The `Player` class already has a method named `duck` and no field with the same
name. So this will be the generated bindings for it:

```dart
// Dart Bindings - Boilerplate omitted for clarity.
class Player extends JObject {
  void duck() { /* ... */ }
}
```

`DuckOwningPlayer` inherits the `duck()` method from `Player` and adds a field
named `duck`. This time, the field will be renamed as the method is simply
inherited.

```dart
// Dart Bindings - Boilerplate omitted for clarity.
class DuckOwningPlayer extends Player {
  Duck get duck$1 { /* ... */ };
  set duck$1(Duck value) { /* ... */ }
}
```

### Identifiers containing dollar signs

JNIgen uses dollar signs in the generated code to fill the syntactic and
semantic gaps between Java and Dart. This normally does not cause a problem as
the
[Java language specificifaction](https://docs.oracle.com/javase/specs/jls/se11/html/jls-3.html#jls-3.8)
suggests dollar signs should be used only in the generated code or, rarely, to
access pre-existing names on legacy systems.

JNIgen replaces each single dollar sign with two dollar signs. For example
`generated$method$2` will turn into `generated$$method$$2`. This prevents name
collision as JNIgen-renamed identifiers will end with an odd number of dollar
signs (optionally followed by a numeric suffix).

### Identifier starting with underscore (`_`)

Unlike Java, Dart identifiers that start with an underscore are private. This
means they are inaccessible outside their defining scope. Users should still be
able to access public Java identifiers that start with an underscore from the
generated Dart bindings. To allow this, JNIgen prepends such identifiers with a
dollar sign to keep them public in Dart.

For example, `_Example` in Java will be converted to `$_Example` in the Dart
bindings:

```java
// Java
public class _Example {
  public void _printMessage() {
    System.out.println("Hello from Java!");
  }
}
```

```dart
// Dart Bindings - Boilerplate omitted for clarity.
class $_Example extends JObject {
  void $_printMessage() { /* ... */ }
}
```

### Inner classes

Java has the concept of inner classes, while Dart does not. Therefore, inner
classes are generated as separate classes named using the name of their
outer-class followed by a dollar sign (`$`) followed by their original name.

For example:

```java
// Java
public class Outer {
  public class Inner {}
}
```

will be turned into:

```dart
// Dart Bindings - Boilerplate omitted for clarity.
class Outer extends JObject {}

class Outer$Inner extends JObject {}
```
