Mastering Dart: A Deep Dive into 'super' Keyword

Mastering Dart: A Deep Dive into 'super' Keyword

Introduction

The world of object-oriented programming in Dart can be a powerful tool, but sometimes it can feel like there's a secret handshake you need to know. One of those mysterious characters is the super keyword. Fear not, fellow coders, for today we'll unveil its magic and make you a superhero of Dart!

Exploring 'super'

Imagine you're part of a big family, and your grandma makes the most delicious chocolate chip cookies in the world. You want to bake your own version, but with a twist – adding peanut butter chips! You wouldn't throw away grandma's recipe entirely, would you? Instead, you'd use her recipe as a base and add your own twist.

That's exactly what the super keyword does in Dart. It allows you to call the constructor or methods of a parent class from within a subclass. It's like saying, "Hey parent, I'm using your recipe, but here's my special ingredient!"

Syntax:

// To access parent class variables
super.variable_name;

// To access parent class method
super.method_name();

Why use 'super'?

  • Initializing the parent class: When you create a subclass, it's important to initialize the parent class first to ensure its properties are set up correctly. super helps you achieve this.

  • Overriding methods: Sometimes, you might want to change the behavior of a method inherited from the parent class in your subclass. super allows you to call the original method from the parent class while adding your own modifications.

Let's get coding!

Examples

Example #1

class Animal {
  String name;

  Animal(this.name);

  void traits() {
    print('Need oxygen');
    print('Eventually die');
    print('Reproduce');
    print('Have senses');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name); // Call the parent constructor

  @override // Mark method as overriding
  void traits() {
    super.traits(); // Characteristics dogs inherit as animals
    print("$name is friendly towards humans"); // Acquired traits
  }
}

void main() {
  Dog myDog = Dog('Buddy');
  myDog.traits(); 
}

In this example:

Animal Class:

The Animal class acts as a blueprint for generic animals. It stores their name and defines a traits method that outlines basic characteristics shared by most animals, like needing oxygen, reproducing, and having senses.

Dog Class:

The Dog class inherits from Animal, gaining all its properties and methods. It has its own constructor that initializes the inherited name and overrides the traits method. This method showcases two key concepts:

  • The line super(name); in your code snippet might seem confusing at first glance, but it's actually quite simple once you break it down. Let's dissect it part by part:

    • super: This keyword refers to the parent class of the current class. In your example, since Dog inherits from Animal, super refers to the Animal class.

    • (name): This part is the argument being passed to the constructor being called. Here, name is being passed as an argument to the constructor.

Putting it together: The entire line super(name); essentially means: "Call the constructor of the parent class (Animal) and pass the argument name to it."

  • super.traits();: This line calls the parent class's traits method from within the overridden traits method of the Dog class. This allows the Dog class to leverage the shared animal characteristics defined in the parent class while adding its own specific traits.

In Essence:

The code demonstrates inheritance, where Dog is a specialized version of Animal with additional specific traits built upon the shared animal characteristics.

Can you write code based on this story?
A cherished box of chocolates, passed down through generations. Grandpa starts with a Hershey's Bar, proudly displaying his gift. Dad inherits the tradition, adding a Ferrero Rocher and showcasing the growing collection. Finally, the son receives the box, but with a twist: he devours all the chocolates, leaving it empty. This code, through inheritance, reflects how each generation builds upon the last, adding their unique touch to the family legacy.

Example #2 (Optional)

This is an example of Multilevel Inheritance:

class Grandpa {
  List<String> chocolates = [];
  void openBox() {
    print("Grandpa adds a Hershey's Bar!");
    chocolates.add('Hershey Bar');
    print("In the box: ${chocolates.join(", ")}\n");
  }
}

class Dad extends Grandpa {
  @override
  void openBox() {
    super.openBox();
    print('Dad adds a Ferrero Rocher!');
    chocolates.add('Ferrero Rocher');
    print("In the box: ${chocolates.join(", ")}\n");
  }
}

class Son extends Dad {
  @override
  void openBox() {
    super.openBox();
    print('Son eats all chocolates');
    chocolates.clear();
    print("In the box: ${chocolates.join(", ")}");
  }
}
Grandpa adds a Hershey's Bar!
In the box: Hershey Bar

Dad adds a Ferrero Rocher!
In the box: Hershey Bar, Ferrero Rocher

Son eats all chocolates
In the box:

Addressing Potential Confusion

Have you ever considered why 'chocolates' is used instead of 'super.chocolates'?

This is because chocolates is a class property shared by all inherited classes. If it were a local variable within a method, super.chocolates would be necessary to access the inherited list. This situation doesn't apply in the given code, so chocolates is suffice.

Takeaways: Mastering the 'super' Keyword

  • super allows you to call methods and access variables from the parent class within a subclass. This is like using an inherited family recipe as a base and adding your own twist.

  • Use super to initialize the parent class constructor when creating a subclass, ensuring proper setup.

  • Employ super to override methods in subclasses, allowing you to modify inherited behavior while preserving core functionality.

  • Remember, super is used with class properties (like chocolates in our example) and not local variables within methods.

  • Start with understanding single-level inheritance before exploring more complex inheritance structures.

  • By effectively using super, you can leverage existing functionalities while adding your own unique contributions, just like generations building upon family traditions.

By understanding these key points, you've gained a solid foundation for using super effectively in your Dart projects. Remember, inheritance is a powerful tool for building reusable and maintainable code. Practice and explore different scenarios to solidify your grasp on this concept and unlock its full potential!

Conclusion

By understanding super, you've unlocked a powerful tool for building complex object-oriented structures in Dart. Remember, inheritance allows you to leverage existing functionalities while adding your own unique contributions, just like generations building upon family traditions.

Further Reading

Thank You!

If you have any queries please comment down below.
Happy learning, everyone!