DEV Community

Cover image for Practical Intro to Operator Overloading in Dart
Ethiel ADIASSA
Ethiel ADIASSA

Posted on

Practical Intro to Operator Overloading in Dart

Introduction

Operator overloading is a quite powerful, popular, and common concept and feature in Object Oriented world. For people not familiar with that, it allows developers to redefine and customize the behavior of standard operators(+,-,%, etc) when used on user-created objects.
Several object-oriented languages (like Dart, Java, C++,...) come with built-in support for it.

In traditional programming, these operators are defined to work with built-in data types such as integers, floats, and strings. However, operator overloading allows you to define the behavior of these operators on your own objects. For example, if you have a class that represents complex numbers, you can define how the addition and subtraction operators work on instances of that class.

How it works

Syntax

ClassRoom operator + (Object o){
  //Your logic here
}
Enter fullscreen mode Exit fullscreen mode

Here are some key points to note about the syntax:

  • the reserved keyword operator and the specific operator we want to overload: the plus operator in this case: +;
  • the operands: Object o is the right-hand side operand and the class we overload the operator on is the left-hand side one;
  • the return type ClassRoom the function should return.

Now that the concepts and syntax are clearly defined, let's get to a practical example. Let's assume we have a classroom with some students we want to keep track of. We also want to add new students to the classroom.

We should have one class to represent the ClassRoom and another one for the User.

class ClassRoom {
  final List<Student> students;

  ClassRoom(this.students);
}
Enter fullscreen mode Exit fullscreen mode
class Student {
  final String name;
  final int age;

  Student(this.name, this.age);

  @override
  String toString() {
    return 'Student{name: $name age: $age}';
  }
}
Enter fullscreen mode Exit fullscreen mode

Let's overload the + operator to fit our use case.

ClassRoom operator + (List<Student> others){
    List<Student> students = [this,...others];
    return ClassRoom(students);
}
Enter fullscreen mode Exit fullscreen mode

Now your Student class should look like the following:

class Student {
  final String name;
  final int age;

  Student(this.name, this.age);

  ClassRoom operator + (List<Student> others){
    List<Student> students = [this,...others];
    return ClassRoom(students);
  }

  @override
  String toString() {
    return 'Student{name: $name, age: $age}';
  }
}
Enter fullscreen mode Exit fullscreen mode
  • the reserved keyword operator and the specific operator we want to overload: the plus operator in this case: +;
  • the return type ClassRoom, we add the current student to the list of the students and return it.

From now on, every time we can use the plus operator like the following:

ClassRoom classRoom =  Student("Andrew",20) + [Student("John",14) ,  Student("Jane", 13)] ;
Enter fullscreen mode Exit fullscreen mode

And if we print the classRoom object, we should get:

[Student{name: Andrew, age: 20}, Student{name: John, age: 14}, Student{name: Jane, age: 13}]
Enter fullscreen mode Exit fullscreen mode

Another example

Now let's want to get the older student of the classroom. This will get us to overload another operator, it can be > or < depending on your preference. We'll go with > for simplicity.

Student operator > (Student other){
    return age > other.age ? this : other;
}
Enter fullscreen mode Exit fullscreen mode

The syntax is pretty much the same.

  • the reserved keyword operator and the specific overloaded operator >;
  • the return type Student, we want to return the oldest student so we compare the current student's age with his comrade's one and return the greatest one.

Now we can use our operator like the following:

Student oldest= classRoom.students.reduce((prev, student)=> prev > student );

The reduce method reduces a list to a single value based on the provided function. We return the oldest student in the class room.

If we print oldest, we should get the expected result:

Student{name: Andrew, age: 20}

Conclusion

With those above examples we have seen how powerful operator overloading is and how concise and easier to read it can make our code by allowing you to use familiar operators with our custom objects. However, it's important to use operator overloading judiciously and with care, as it can lead to code that is difficult to understand and maintain if overused or used incorrectly.
For additional resources you can head to the following links:

Acknowledgments

Thanks to the author of this article since he's inspired mine.

Top comments (1)

Collapse
 
ablor_endy profile image