Interfaces in Object Oriented Programming Languages and Prototype-based Languages

Interfaces in Object Oriented Programming Languages and Prototype-based Languages

Interfaces

An interface defines which methods and properties a class must implement.  

Interfaces are a key concept in OOP. 

Interfaces specify what a class must do but not how they go about doing it. The interface itself does not contain any code to implement an object. Therefore a class is used to implement an interface, interfaces have to be implemented by a class before you can access them. 

Therefore, the interface hides all unnecessary implementation from the user.

Thus one can say that interfaces are used to achieve abstraction, as abstraction involves showing only the relevant data and hiding all unnecessary details of an object from the user.

This is a notable benefit to the use of interfaces as you can use an interface to achieve security i.e. hide certain details and only show the important details of an object (interface).

Another key benefit that software developers use interfaces is to ensure that all classes are built according to rules, or contracts, outlining what methods and properties must be implemented.

An interface is often referred to as a contract because it is agreed that a class that implements the interface will implement the properties and methods defined in the interface.

Further, using interfaces is also a way of enforcing strict typing to a certain degree.

For example, Python supports the implementation of interfaces because it is an OOP language. 

JavaScript

On the other hand, JavaScript has no built-in way of creating or implementing interfaces. 

It also lacks built-in methods for determining whether an object implements the same set of methods as another object, making it difficult to use objects interchangeably. 

In JavaScript, almost "everything" is an object.

  • Booleans can be objects (if defined with the new keyword)
  • Numbers can be objects (if defined with the new keyword)
  • Strings can be objects (if defined with the new keyword)
  • Dates are always objects
  • Maths are always objects
  • Regular expressions are always objects
  • Arrays are always objects
  • Functions are always objects
  • Objects are always objects

There are different ways to create new objects in Javascript.

There are different ways to create new objects:

  1. Create a single object, using an object literal.
  2. Create a single object, with the keyword new.
  3. Define an object constructor, and then create objects of the constructed type.
1. 

const person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};

2. 

const person = new Object();
  person.firstName = "John";
  person.lastName = "Doe";
  person.age = 50;
  person.eyeColor = "blue";

3.
 
function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
  this.nationality = "English";

}

Since interfaces are a contract that defines what classes should look like and JavaScript doesn’t use classes to create objects this makes sense.  

It is for this reason that Javascript has no built-in way of creating or implementing interfaces.

However, JavaScript is very flexible and there are several ways in which we can achieve the goals of interfaces using JavaScript.

One could emulate interfaces using JavaScript by use of:

  • comments, 
  • attribute checking, and 
  • duck typing. 

No single technique is perfect, but a combination of all three will come close.

Describing Interfaces with Comments

The easiest and least effective way of emulating an interface is with comments. Mimicking the style of other object-oriented languages, the interface and implements keywords are used but are commented out so they do not cause syntax errors.

There are some benefits to this approach. It’s easy to implement, requiring no extra classes or functions. It promotes reusability because classes now have documented interfaces and can be swapped out with other classes implementing the same ones. It doesn't affect file size or execution speed; the comments used in this approach can be trivially stripped out when the code is deployed, eliminating any increase in file size caused by using interfaces. 

However, it doesn't help in testing and debugging since no error messages are given.

Emulating Interfaces with Attribute Checking

The second technique is a little stricter. All classes explicitly declare which interfaces they implement, and these declarations can be checked by objects wanting to interact with these classes.

There are several benefits to this approach. You are documenting what interfaces a class implements. You will see errors if a class does not declare that it supports a required interface. You can enforce that other programmers declare these interfaces through the use of these errors. The main drawback to this approach is that you are not ensuring that the class really does implement this interface. You only know if it says it implements it. It is very easy to create a class that declares it implements an interface and then forget to add a required method. 

All checks will pass, but the method will not be there, potentially causing problems in your code. It is also added work to explicitly declare the interfaces a class supports.

Emulating Interfaces with Duck Typing

In the end, it doesn't matter whether a class declares the interfaces it supports, as long as the required methods are in place. That is where duck typing comes in. Duck typing was named after the saying, “If it walks like a duck and quacks like a duck, it's a duck.” It is a technique to determine whether an object is an instance of a class based solely on what methods it implements, but it also works great for checking whether a class implements an interface. The idea behind this approach is simple: if an object contains methods that are named the same as the methods defined in your interface, it implements that interface.

This differs from the other two approaches in that it uses no comments. All aspects of this are enforceable.

While probably being the most useful of the three methods, it still has some drawbacks. A class never declares which interfaces it implements, reducing the reusability of the code and not self-documenting like the other approaches. It requires a helper class, Interface, and a helper function, ensureImplements. It does not check the names or numbers of arguments used in the methods or their types, only that the method has the correct name.

Lastly, TypeScript can also be used to create JavaScript that uses classes and interfaces which will be covered at the end of this blog post!

Strict Mode in Javascript

Strict mode was introduced in ECMAScript 5 (ES5). It is a semantically stricter or restricted version of JavaScript language that produces errors for those mistakes that are handled silently otherwise.

Strict mode can be used in global scope for the entire script, by adding the string "use strict" at the beginning of your script or it can be applied to individual functions, by adding the string "use strict" in your functions. 

Strict mode makes several changes to normal JavaScript semantics:

  1. Eliminates some JavaScript silent errors by changing them to throw errors.
  2. Fixes mistakes that make it difficult for JavaScript engines to perform optimisations: strict mode code can sometimes be made to run faster than identical code that's not strict mode.
  3. Prohibits some syntax likely to be defined in future versions of ECMAScript.

Strict mode makes it easier to write "secure" JavaScript. It changes previously accepted bad syntax into real errors. 

Therefore, strict mode reduces bugs, improves security and overall performance of your application.

TypeScript

TypeScript is designed by Microsoft and compiles into plain JavaScript. TypeScript is a typed superset of JavaScript. TypeScript makes JavaScript a statically-typed language instead of a loosely-typed language. 

Statically typed languages, you have to specify what data type a variable will contain when you declare it. If you declared a variable as a string in a statically typed language and later try to assign that variable a value that is a number, it would throw an error. 

However, with dynamically typed languages, object types are determined at runtime. Therefore, you can declare a variable that can hold a string at one point in time but a number at another stage

Therefore  TypeScript allows for the usage of interfaces. As we know from above, an interface adds the functionality of strong type checking for your functions, variables, or the class that is implementing the interface. Thus we can see how TypeScript makes JavaScript a statically-typed language.

One of TypeScript’s core principles is that type checking focuses on the shape that values have. The TypeScript compiler does not convert interface to JavaScript but it uses interface for type checking. This is sometimes called “duck typing” as we have seen above in emulating interfaces for JavaScript! 

Overall TypeScript provides a way to describe the shape of an object, better documentation and validation to check whether your code is working as expected. 

References

HyperionDev Class Notes (2021)








Comments

Popular posts from this blog

Big O Notation Basics for Web Developer