Tips & Tricks: Only Fields are ‘private’ by Default

Programmers often complain about the verbosity of Java. Once you specify all the modifiers that must be applied, it’s not difficult to see how it can quickly become verbose:

public static void veryLongNamingConventions() {
    // ...
}

JS++ does this differently. Following the OOP principle of encapsulation, JS++ provides convenient default rules for access modifiers.

By default, only fields (variable members of classes) are private. All other class members – such as methods, getters, setters, and constructors – are public by default.

This makes it very easy to write concise code:

class Point
{
    int x, y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    int getX() { return this.x; }
    int getY() { return this.y; }
}

In the above code, the fields x and y are private. Meanwhile, the constructor and the getX/getY methods are all public. We can be explicit and manually specify the access modifiers, but it’s not necessary in JS++.

Tips & Tricks: Structural Typing (in a Nominal Type System) with ‘auto’ Type Inference

By default, JS++ uses nominal typing over structural typing. However, structural typing can be achieved using auto.

The following is a contrived example but illustrates a consideration in your application when using auto:

class Foo
{
    bool isError() { return false; }
}

auto foo = new Foo();
if (foo.isError()) {
    exit(1);
}

Now, during refactoring:

class Foo
{
    bool isError() { return false; }
}
class Bar
{
    bool isError() { return true; }
}

auto foo = new Bar(); // type changed
if (foo.isError()) { // this effectively becomes static duck typing
    exit(1);
}

Since the variable foo above effectively becomes “duck typed” (or, more precisely, structurally typed), it becomes harder for the compiler to potentially catch your errors.

While the above example is contrived, it’s not difficult to see how this can crop up in more complex applications.

JS++ 0.8.5: Bug Fix Release

This is a small bug fix release.

The following minor issues have been fixed:

  1. Dictionary expression of empty arrays now has the correct type inferred
  2. Labels for foreach statements
  3. Type inference for System.Array.reduce
  4. Function inlining for System.String methods: padRight(int), padLeft(int), startsWith, endsWith

Issue #1:

Dictionary<unsigned int[]> x = {
    "foo": (unsigned int[]) [],
    "bar": (unsigned int[]) []
};

The casts were previously required in 0.8.4, but, in the latest release, casting of empty arrays is no longer necessary.

Issue #2:

outerLoop: foreach (var row in json) {
    // ...

    foreach(var cell in row.Cell) {
        // ...
        continue outerLoop;
    }
}

Issue #3:

string[] keys = dict.keys();
int x = keys.reduce(
    int(string previous /* type of 'previous' param */, string current) {
    },
    0 // and this type
);

In the above case, the two types must match. However, the type checker was inferring ‘external’ instead. This has been fixed in the latest release.