How an interface can be useful in object-oriented

An interface serves many roles. We saw that you can define a contract for particular objects with an interface. However, interfaces can do much more.

An interface defines which members you want the consumer of your library to see and use. The public, private, and protected visibility keywords serve the same purpose. However, in some cases, you may need to have public members and still not allow everyone to use them. One reason can be that you want to have deep access to unit testing, hence having most of your members public allows you to black boxing functions testing. However, it might expose too much. Therefore, an interface can define every member that is accessible and be implemented by a class. Instead of passing the reference to the class directly, the interface is distributed externally while you can use the class internally:

class ClassA {
public mainFunction(): void
{
this.subFunction1();
this.subFunction2();
}

private subFunction1(): void { }
private subFunction2(): void { }
}

The class has two private functions that are executed by the main function, named mainFunction. However, the encapsulation does not allow us to unit test the private function without using some hack to access these functions. We want to avoid casting the main object to any to access the function because, if these functions change, the test might fail not because of wrong logic but because TypeScript was not able to refactor the function since the type was coerced to any. A better practice is to use an interface to keep the type present at all times:

interface IClassA {
mainFunction(): void;
}

class ClassA2 implements IClassA {
public mainFunction(): void {
this.subFunction1();
this.subFunction2();
}

public subFunction1(): void { }
public subFunction2(): void { }
}

Everything is public, however, all the system is using IClassA instead of the class directly providing the encapsulation desired. The unit test can use the class and access the original private function.

A second case where the interface shines is that it allows us to have many concrete implementations of a specific type. You can define an interface that will be consumed by a function and has many implementations of this one. In the following example, we have a consume function that takes IElement as input. There are two concrete implementations of IElement, which gives the code the flexibility to have many element implementations. This help to reduce customized code in the consuming function by having a type that represents the minimum set of members needed to perform the task:

interface IElement {
m1: string;
}

class E1 implements IElement { m1: string = "E1->m1"; a: number = 1; }
class E2 implements IElement { m1: string = "E2->m1"; b: boolean = true; }

class ClassB {
public consume(element: IElement): void { }
}
..................Content has been hidden....................

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