In this article, we will learn about basics of OOPs. In Object Oriented Programming we have 9 thing to understand like Namespace, Class, Object, Property, Method, Constructor, Inheritance, Encaplulation/Abstraction and Polymorphism.
We will cover all this 9 principle hear below with examples in Javascript and Typescript.
Namespace
Namespace is a container which lets developers bundle all functionality under a unique, application-specific name. It can help us to control the scope of class and method names in larger programming projects.
Class
Class defines the object's characteristics. A class is a template definition of an object's properties and methods.
Class is The "blueprint" from which other more specific instances of the object are drawn.
JavaScript is a prototype-based language. JavaScript uses functions as classes. Defining a class is as easy as defining a function.
//Define the class Car function Car() { }
class car { }
Object
Object is an instance of a class.
Object refers to a data structure containing data and instructions for working with the data.
Objects sometimes refer to real-world things, for example a car or map object in a racing game.
The difference between Object and class is Objects hold any information , but classes don’t have any information. Definition of properties and functions can be done at class and can be used by the object.
For creating instances of any class i.e. objects we use new keyword.
function Car() { } var car1 = new Car(); var car2 = new Car();
class car { } let car1 = new car(); let car2 = new car();
Property
Property is an object characteristic, such as color
A property is a characteristic of an object, often describing attributes associated with a data structure. It exists to kind of properties: an Instance Property which holds data specific to a given object instance, or a Static Property which holds data shared between all object instances.
function Car(speed) { this.speed = speed; } var car1 = new Car(40); var car2 = new Car(60); alert("Car1 Speed: " + car1.speed); alert("Car2 Speed: " + car2.speed);
class Car { speed: string; constructor(speed: string) { this.speed = speed; } } let car1 = new Car('40'); let car2 = new Car('60'); alert("Car1 Speed: " + car1.speed); alert("Car2 Speed: " + car2.speed);
Method
Method is an object capability, such as walk. It is a subroutine or function associated with a class.
It exist two kind of methods: Instance Method which are built-in tasks performed by an object instance, or Static Methods which are tasks that can be performed without the need of an object instance.
In JavaScript functions themselves are objects, so, in that context, a method is actually an object reference to a function.
To define methods in a Class, all you have to do is just define a attribute and assign an function to it.
function Car() { }; Car.prototype.speed= 'Car Speed'; Car.prototype.setSpeed = function(speed) { this.speed = speed; alert("Car speed changed"); }; var car1 = new Car(40); var car2 = new Car(60); car1.setSpeed(120); car2.setSpeed(140);
class Car { speed: string; setSpeed(speed: string) { this.speed = speed; alert("Car speed changed"); } } let car1 = new Car(); let car2 = new Car(); car1.setSpeed('120'); car2.setSpeed('140');
Constructor
Constructor is a method called at the moment an object is instantiated. It usually has the same name as the class containing it.
A constructor belongs to a particular class object that is instantiated. The constructor initializes this object and can provide access to its private information. Essentially, a constructor in JavaScript is usually declared at the instance of a class.
As in JavaScript there is no class keyword and the function serves as class definition, there is no need of defining constructor explicitly. The function defined for the class acts as constructor.
function Car(speed) { this.speed = speed; alert('car is initialised'); } var car1 = new Car(40); var car2 = new Car(50);
class Car { speed: string; constructor(speed: string) { this.speed = speed; alert('car is initialised'); } } var car1 = new Car('40'); var car2 = new Car('60');
Inheritance
Inheritance is when a class can inherit characteristics and capabilities from another class.
JavaScript supports single class inheritance. To create a child class that inherit parent class, we create a Parent class object and assign it to the Child class. In following example we created a child class Ferrari from parent class Car.
//Define the Car class function Car() { } Car.prototype.speed= 'Car Speed'; Car.prototype.setSpeed = function(speed) { this.speed = speed; alert("Car speed changed"); } //Define the Ferrari class function Ferrari() { } Ferrari.prototype = new Car(); // correct the constructor pointer because it points to Car Ferrari.prototype.constructor = Ferrari; // replace the setSpeed method Ferrari.prototype.setSpeed = function(speed) { this.speed = speed; alert("Ferrari speed changed"); } var car = new Ferrari(); car.setSpeed();
class Car{ speed: String; setSpeed(speed: string) { this.speed = speed; alert("Car speed changed"); } } class Ferrari extends Car{ speed: String; setSpeed(speed: string) { this.speed = speed; alert("Farrari speed changed"); } } var car = new Ferrari(); car.setSpeed('');
Encapsulation
Encapsulation and abstraction is a mechanism that lets our program to hide unwanted code within a capsule and shows only essential features of an object.
Encapsulation is used to hide its members from outside class or interface, whereas abstraction is used to show only essential features.
In JavaScript, encapsulation is achieved by a a self invoking anonymous function expression.
JavaScript variables have either function scope, or global scope. There is no block scope. Enclosing our code in a self invoking function like the one in our example creates a temporary local scope for single-use, immediately-run code, without polluting the global namespace.
(function() { var x = ''; function myFunction () { alert('Hello: ' + x); } x = 'Bob'; myFunction(); alert(typeof x); // string alert(typeof myFunction); // function })(); alert(typeof x); // undefined alert(typeof myFunction); // undefined
Whatever we declare the self invoking function is held in a separate scope. The variable x and the function myFunction() cannot be accessed from anywhere else and it would be free to declare another function myFunction() without conflicts.
In TypeScript we have option to declare Public, private, and protected modifiers like other OOP languages to do Encapsulation. In typescript all it's member are Public by default.
Typescript Private modifier
class Animal { private name: string; constructor(theName: string) { this.name = theName; } } new Animal("Cat").name; // Error: 'name' is private;
Typescript Protected modifier
The protected modifier acts much like the private modifier with the exception that members declared protected can also be accessed by instances of deriving classes. For example
class Person { protected name: string; constructor(name: string) { this.name = name; } } class Employee extends Person { private department: string; constructor(name: string, department: string) { super(name); this.department = department; } public getElevatorPitch() { return `Hello, my name is ${this.name} and I work in ${this.department}.`; } } let howard = new Employee("Howard", "Sales"); console.log(howard.getElevatorPitch()); console.log(howard.name); // error
Polymorphism
Poly means "many" and morphism means "forms". Different classes might define the same method or property.
Polymorphism is the presentation of one interface for multiple data types.
There are two approaches by which we can use Polymorphism in JavaScript. One by checking the argument types or by another approach by tracking an object at the last argument of a function.
Polymorphism by Checking Argument Type
function CatStrings(p1, p2, p3) { var s = p1; if(typeof p2 !== "undefined") {s += p2;} if(typeof p3 !== "undefined") {s += p3;} return s; }; CatStrings("one"); // result = one CatStrings("one",2); // result = one2 CatStrings("one",2,true); // result = one2true
Polymorphism by Tracking an object
function foo(a, b, opts) { } foo(1, 2, {"method":"add"}); foo(3, 4, {"test":"equals", "bar":"tree"});
However TypeScript end result is Plain JavaScript, we can only provide the single method block. Through the use of conditional statements;
class Car{ setSpeed(message: string); setSpeed(message: number); setSpeed(message: boolean); setSpeed(message: any) { if (typeof message === "string") { alert(message); } else if (typeof message === "number") { alert("The number provided was: " + message); } else if (typeof message === "boolean") { alert("The boolean value was: " + message); } else { alert(message); } } } var car = new Car(); car.setSpeed(false);