DEV Community

Cover image for OOP - Abstraction - Part 1
Sivakumar Natarajan
Sivakumar Natarajan

Posted on • Edited on

OOP - Abstraction - Part 1

What ?

Definitions

Part 1: Abstraction provides a blueprint or plan for designing classes with a defined set of rules. It ensures consistency and enforces that certain behaviors are implemented across derived classes.

Part 2: Abstraction is the process of hiding implementation details from users, enabling them to focus on the functionality rather than the internal workings.

Eg: A commonly used analogy is the TV remote control: users interact with buttons to operate the TV without needing to know how the internal mechanics work.

I find Part 1 to be more intuitive and easy to explain so this post explains in detail Part 1 of the definition.

Part 2 is explained in detail here.

Why a blueprint?

To understand the need for abstraction (a blue print), let’s first explore a problem.

Problem:

Imagine creating classes to draw pictures of animals. Each animal has its own unique features, but certain traits—such as having four legs and a tail—are shared among them. Without a structured approach, developers might forget to include these common traits, leading to incomplete or inaccurate depictions.

class DogPicture {
  drawATail() {}

  drawFourLegs() {}

  drawFloppyEars() {}
}

class CatPicture {
  drawATail() {}

  drawFourLegs() {}

  drawConeShapedEars() {}
}

class HorsePicture {
  drawATail() {}

  drawFourLegs() {}

  drawManeHair() {}
}

class GoatPicture {
  drawATail() {}

  drawFourLegs() {}

  drawHorns() {}
}

class ZebraPicture {
  drawATail() {}

  drawFourLegs() {}

  drawStripesOnBody() {}
}
Enter fullscreen mode Exit fullscreen mode

Solution:

Abstraction can solve this problem by defining a shared plan or rules that every animal picture class must follow. This can be achieved using an abstract class or interface in TypeScript.

abstract class AnimalPicture {
  abstract drawFourLegs(): void;

  abstract drawATail(): void;
}
Enter fullscreen mode Exit fullscreen mode

Now, any class that implements AnimalPicture must define these methods. Failing to do so will result in an error.

Incorrect implementation

class DogPicture implements AnimalPicture { // this will throw error as `drawFourLegs` & `drawATail` are not implemented. 
  drawFloppyEars() {}
}
Enter fullscreen mode Exit fullscreen mode
Error:
Class 'DogPicture' incorrectly implements class 'AnimalPicture'. Did you mean to extend 'AnimalPicture' and inherit its members as a subclass?
  Type 'DogPicture' is missing the following properties from type 'AnimalPicture': drawFourLegs, drawATailts(2720)
Enter fullscreen mode Exit fullscreen mode

Correct implementation

class DogPicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a dog.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a dog.");
  }
  drawFloppyEars() {}
}

class CatPicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a cat.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a cat.");
  }
  drawConeShapedEars() {}
}

class HorsePicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a horse.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a horse.");
  }
  drawManeHair() {}
}

class GoatPicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a goat.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a goat.");
  }
  drawHorns() {}
}

class ZebraPicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a zebra.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a zebra.");
  }
  drawStripesOnBody() {}
}

Enter fullscreen mode Exit fullscreen mode

This ensures that all animal picture classes implement the shared rules (drawFourLegs and drawATail), while allowing flexibility for unique features like floppy ears or stripes.

Types of abstract classes:

- Pure abstract class

These classes are plain blueprints that won't have any concrete/implemented methods.

// pure abstract class
abstract class AnimalPicture {
  abstract drawFourLegs(): void;

  abstract drawATail(): void;
}
Enter fullscreen mode Exit fullscreen mode

In Typescript these pure abstract classes (with no access privilege needs like protected) can be replaced with interfaces which is as well could as a blue print.

// interface
interface AnimalPicture {
  drawFourLegs(): void;

  drawATail(): void;
}

//usage
class HorsePicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a horse.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a horse.");
  }
  drawManeHair() {}
}
Enter fullscreen mode Exit fullscreen mode

- Impure/partial abstract class:

Abstract classes that have one or more concrete methods along with a few abstract attributes(methods/properties).

These classes can be extended(inherited) to create sub classes.

Defining the abstract class

// impure abstract class
abstract class AnimalPicture {
  // Concrete method 1
  protected drawFourLegs() {
    console.log(`drawing common four legs feature`);
  }

  // Concrete method 2
  protected drawATail() {
    console.log(`drawing common tail feature`);
  }

  // Abstract method 1
  protected abstract drawUniqueFeature(): void;

  // Concrete method 3
  public drawFinalPicture() {
    this.drawATail();
    this.drawFourLegs();
    this.drawUniqueFeature();
  }
}
Enter fullscreen mode Exit fullscreen mode

Extending the abstract class

class DogPicture extends AnimalPicture {
  // because its inheritance, calling the super/parent class is required.
  constructor() {
    super();
  }
  // Abstract method 1 implemented
  protected drawUniqueFeature(): void {
    console.log("Drawing four legs for a dog.");
  }
}
Enter fullscreen mode Exit fullscreen mode

Usage

const dog = new DogPicture();
// Concrete method 3 of abstract class is inherited
dog.drawFinalPicture();
Enter fullscreen mode Exit fullscreen mode

Part1(abstract as blueprint) Conclusion

Abstraction in OOP helps enforce a consistent structure across related classes while allowing flexibility for unique implementations. It ensures that essential behaviors are not overlooked, making code more predictable and maintainable.

Also, please carryon reading the part2 post to understand the part2 of the definition.

Top comments (0)