How to implement inheritance in Ballerina

If I'm not mistaken, you are trying to map the OOP concepts found in popular languages such as Java to Ballerina right? While it's tempting to do so, that can actually be a counter productive effort. Instead of attempting to think of a solution to a problem in an object oriented manner and trying to write OOP-style code in Ballerina, it would be better to take time to get familiar with the type system and other constructs Ballerina provides and build up the solution using those constructs. The Ballerina by Examples (BBEs) would be a good place to start.

Having said that, I'll try to briefly answer the questions you've raised. The Ballerina type system is structural. In Java, any user defined type is an object and you use inheritance to establish the relationships between the types. In Ballerina, we compare the "shape" of the value to check if it is compatible with a particular type. Every value has a shape, and a type is a set of such shapes. Here's what the 2020R1 spec of the language says regarding this and subtyping:

A type denotes a set of shapes. Subtyping in Ballerina is semantic: a type S is a subtype of type T if the set of shapes denoted by S is a subset of the set of shapes denoted by T. Every value has a corresponding shape. A shape is specific to a basic type: if two values have different basic types, then they have different shapes.

Let's take a concrete example using records to further explain this.

type Person record {
    string name;
    int age;
};

type Student record {
    string name;
    int age;
    string school;
};

public function main() {
    Student st = {name: "John Doe", age: 18, school: "XYZ Academy"};
    Person p = st; // this is a valid assignment
    io:println(p);
}

In the above code snippet we can safely use a Person reference to manipulate a Student value since a Student value is guaranteed to have the same fields as a Person value.

The Student record definition can be written as follows as well:

type Student record {
    *Person; // this is a type reference
    string school;
};

Referring a type as given above copies all the fields in the specified record to the current record. While this may look like inheritance, it's not. The definition above is equivalent to the the original definition we saw earlier.

In Ballerina, code is organized by modules. Similar to packages in Java, except that a module is made up of functions, type definitions (e.g., records, objects), services, listeners, constants etc. While objects are supported, it's just another type of values; not a unit of organization for code. Functions are a module level construct and if you intend to reuse it in other modules, it needs to have the public access modifier. To call the function, you need to import the module and qualify the function call with the module name. e.g.,

int x = foo:barFunction();

Sharing variables across modules is not allowed in Ballerina. However, you can have public constants in a module. e.g.,

public const PI = 3.14;

Hope this clears things up. If you are interested in the design of the language, you can refer to the language spec I mentioned earlier and to the following blog posts from James:

  • Ballerina Programming Language - Part 0: Context
  • Ballerina Programming Language - Part 1: Concept

Also, note that 0.991 is a heavily outdated version. I'd recommend taking a look at the current version (1.2.2).


Ballerina does not support the implementation inheritance or class-based inheritance that you see in OO languages like Java. What this means is that you cannot inherit code from types in Ballerina (e.g. Ballerina objects).

The term inheritance is an overloaded term. If you want to know more about sybtyping in Ballerina, then read Pubudu's answer. It explains how you can achieve interface inheritance in Ballerina. You can map his answer to Ballerina objects as well.

Tags:

Wso2

Ballerina