Bringing abstraction with an abstract class

Abstraction is an object-oriented concept that allows us to have a base class that delegates the implementation of a function to the class that extends the abstract class.

The following example creates the main class by instantiating the custom logic class. It invokes the main function, which will execute the abstract function. To the MainClass class, the abstract function is a black box. It only knows its name, parameter types, and returns types. The example executes the commented block code A-C-B in that particular order:

abstract class MainClass {
public mainCoreLogic(): void {
// Code here [A]
this.delegatedLogic();
// Code here [B]
}

public abstract delegatedLogic(): void;

}


class CustomLogic extends MainClass {

public delegatedLogic(): void {
// Do some custom logic here [C]
}

}

const c: MainClass = new CustomLogic();
c.mainCoreLogic();

The abstract is powerful when you pass a computed value to the abstract class and that this one also returns a result of a custom computation. Here is a second version that shows how two different implementations can occur while the main class remains unchanged. The main class is now named Calculus and has a public function that takes two numbers and returns a Boolean. It does some operations on the parameters and calls the delegated logic. The treatment of the value is unknown to the main class. The significant part of the operation is the result that is then used. On the side of the class that consumes the abstract class by extending the class. It has to provide all abstract functions or fields. Every abstract member becomes a public field at the extended level. In the example, the logic multiplies the two values that return the specified type:

abstract class Calculus {
public isAboveZero(a: number, b: number): boolean {
const positiveA = Math.abs(a);
const positiveB = Math.abs(b);
const result = this.delegatedLogic(positiveA, positiveB);
return result > 0;
}

public abstract delegatedLogic(a: number, b: number): number;
}

class AddLogic extends Calculus {
public delegatedLogic(a: number, b: number): number {
return a * b;
}
}

const multi: Calculus = new AddLogic();
multi.isAboveZero(1, 2);

The code could have been written in a non-object-oriented way by providing by parameter the logic to execute. Here is the same version of the code without an abstract:

 class CalculusWithoutAbstract {
public constructor(private delegatedLogic: (a: number, b: number) => number) {
}

public isAboveZero(a: number, b: number): boolean {
const positiveA = Math.abs(a);
const positiveB = Math.abs(b);
const result = this.delegatedLogic(positiveA, positiveB);
return result > 0;
}
}

const multi2: CalculusWithoutAbstract = new CalculusWithoutAbstract((a, b) => a * b);
multi2.isAboveZero(1, 2);

The version without an abstract takes in the constructor of the class the function to be called instead of the abstract function. The substitution between the two is a matter of preference. The main difference between the two is that using abstract force the abstract implementation to be public when the delegate function can remain private. However, the way to work around the visibility issue is to initialize with the base class instead of the child class:

const multi: Calculus = new AddLogic(); // Expose only the main function
const multi: AddLogic = new AddLogic(); // Expose the delegate function
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.82.4