Inheritance

Use extends to create a subclass, and super to refer to the superclass. When you extends a class, the subclass gets all the instance members of its superclass except for constructor. The constructors doesn't get inherited. If superclass defines static members, or private members, the subclass will also get static and private members. Getter or setter also gets inherited. So the only exception is the constructor. Only constructor doesn't get inherited.

In the following example, we are declaring a class Shape. The class is extended by the Circle class. Since there is an inheritance relationship between the classes, the child class, i.e., the class Circle gets an implicit access to its parent class data member.

void main() { 
   var obj = new Circle(); 
   obj.cal_area(); 
}  
class Shape { 
   void cal_area() { 
      print("calling calc area defined in the Shape class"); 
   } 
}  
class Circle extends Shape {}

// Output --
calling calc area defined in the Shape class

Dart also supports multi-level inheritance. For example, Class B is derived from class A. And class C is derived from class B (A->B->C). In the following example, the class Leaf derives the attributes from Root and Child classes by virtue of multi-level inheritance:

Live Demo
void main() { 
   var obj = new Leaf(); 
   obj.str = "hello"; 
   print(obj.str); 
}  
class Root { 
   String str; 
}  
class Child extends Root {}  
class Leaf extends Child {}  
//indirectly inherits from Root by virtue of inheritance

// Output
hello

Overriding Methods: @override

Subclasses can override instance methods, getters, and setters. You can use the @override annotation to indicate that you are intentionally overriding a member:

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  @override
  void turnOn() {...}
  // ···
}

Overriding operators

You can override an operator that will be used on class operand. For example, lets consider the operator +, which is used on primitive type integer to perform addition operation. But what if you want to use this + operator on class object to perform some operation. In this case you need to override + the operator to give it another functionality to perform addition on class objects.

Following is the syntax of overriding an operator:

return_type operator operator_symbol(parameter_list){
  // return result --
}

In the above syntax operator is a keyword. And operator_symbol represents the actual operator which will be overriden. The return type and the parameter type must be the same as the class type. Here is an example:

class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v){
    return Vector(x + v.x, y + v.y);
  }
  Vector operator -(Vector v){
    return Vector(x - v.x, y - v.y);
  }

  // Operator == and hashCode not shown. For details, see note below.
  // ···
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}

In the above example we have overriden two operator, - and +:

Vector operator +(Vector v){
  return Vector(x + v.x, y + v.y);
}
Vector operator -(Vector v){
  return Vector(x - v.x, y - v.y);
}

Internally, When we perform v + w, it will actually translate into a function call like the following:

v.overriden_operator(w);

So the statement v + w, will pass w as an argument and it will call the function on the object v.