Classes
Classes are a relatively new feature added in ES6 (ECMAScript 2015). It provides a way to define objects and their behavior using a syntax similar to classes in other OOP languages like Java, Python, etc.
The OOP principles include
- Inheritance
- Polymorphism
- Data Encapsulation
- Data Abstraction
Class 🗳️
Describes in general what an object
is with methods and variables.
-
Class declarations are NOT HOISTED:
- Meaning declare class first and then access it
- Otherwise, code like the following will throw a ReferenceError
-
Functions are HOISTED:
- You can call function first and then declare it
- No Error Thrown
class Person {
name;
age;
// methods
sayHello() {
console.log(`Hello, my name is ${this.name} and
I am ${this.age} years old.`);
}
}
Constructor 📝
- Useful when creating an
object
to specify default values of this instance - In inheritance, if child class does not provide a constructor, one will be created by default
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Student extends Person{
// No constructor provided then this is created by default
constructor(...args){
super(...args);
}
}
Objects 📦
objects
are instances of theclass
.- An instance means that an object is created based on the class.
- Use keyword
new
to create a new instance of the class - Only one constructor is allowed
Instantiating 🆕
let person = new Person('John', 30);
person.sayHello();
// output: "Hello, my name is John and I am 30 years old."
toString()
- Like toString in Java, returns default information when object is printed
Symbol
is a primitive data type, called special symbol- This is a way to add
properties
to an object
class Person {
#age; // private field
constructor(age) {
this.#age = age; // Allowed
}
#sayHello() { // private method
console.log(`Hello, I am ${this.#age} years old.`);
}
[Symbol.toPrimitive]() {
return `Person name: ${Person.age}`;
}
}
let new_car = new Car()
console.log(new_car) // Dealership: Terp Cars
Class Access Modifiers 🔐
Instance Variables
Instance Variables
are available across all objects but unique for each object.- In other words, an instance variable from one object differs from another object. For instance:
student_1.name = "Jose"
student_2.name = "Kevin"
- Instance Variables has NO TYPES (Javascript)
class Class {
id;
name;
age;
}
Class Variables
Class Variable
are shared between all objects, using thestatic
keyword.- If the class variable from a object is modified, another object of the same class also updates it.
- All
static
needs to be called with theirClass
name, instead ofthis
. i.e line 10
class Car {
static dealership = "Terp Cars"; // static-public field
static #instances = 0; // static-private field
info() {
return `${Car.#printDealer()}`
}
static #printDealer(){ // can also make static-private functions
Car.#instance++;
return `${Car.dealership}`;
}
}
Public vs Private Variables
Public
- In Javascript, methods and data are public by default
- Public variables are accessible from outside the class and can be accessed with the dot notation (
instanceObject.dataField
)
class Person {
name; // public field
constructor(name) {
this.name = name; // ✅ allowed access
}
}
let person = new Person("Jose")
student_1.name // ✅ allowed access
Private
- Private: cannot be accessed outside of class, only accessible from inside the class
- Defined using the (
#
) symbol before the variable or function name.
class Person {
#age; // private field
constructor(age) {
this.#age = age; // ✅ allowed
}
#sayHello() { // private method
console.log(`Hello, I am ${this.#age} years old.`);
}
}
let person = new Person(30);
console.log(person.age); // ❌ No Allowed since outside of class, Error
person.sayHello() // ❌ No Allowed since private, Error
Wrap Up
-
Public - by default
-
Private - add
#
-
Instance member (non static) - only instances objects can call these members
-
Static member - add
static
, only the Class can call these members
The 4 Principles
OOP allows objects to interact with each other using four basic principles: encapsulation, inheritance, polymorphism, and abstraction.
Inheritance 👨👦
- Inheritance is a way to create a new class that is a modified version of an existing class.
- In JavaScript, inheritance can be achieved using the
extends
keyword. - Rule:
child
extendsparent
class
class Car {
model;
year;
wheels;
static dealership = "Toyota";
static #carSold = 0; // shared all instances, no access outside
constructor(model, year, wheels){
this.model = model;
this.year = year;
Car.#carSold++;
}
// Java's toString()
[Symbol.toPrimitive]() {
return `
Car sold: ${this.model}, ${this.year},
Car sold by: ${Car.dealership}
`;
}
info(){
document.writeln(`
${this.model}, ${this.year}, ${this.wheels},
${Car.dealership}, ${Car.#carSold}`
)
}
// getter
get model(){
return this.model
}
// setter
set model(newModel) {
this.model = newModel;
}
}
class SportsCar extends Car {
#engine;
constructor(model, year, wheels engine) {
super(model, year, wheels);
this.#engine = engine;
}
get engine(){ return this.#engine; }
set engine(newEngine){ this.#engine = newEngine; }
// Overrides info() from Car
info() {
super.info(); // call parent Class method
}
// Overrides toString()
[Symbol.toPrimitive]() {
return `
${super[Symbol.toPrimitive]()}, Engine: ${this.#engine}
`;
}
}
Polimorphism 👥
- Polymorphism is a concept in object-oriented programming that allows objects of different classes to be treated as if they were objects of the same class, as long as they share a common interface or inheritance hierarchy.
- This means that a method can behave differently depending on the object it is called on.
- This can be achieved through method overriding.
- In the example above, the
SportsCar
class overrides theinfo()
method inherited fromCar
class, providing a different implementation for sport car. This method behaves differently depending on the object it is called on, even though the method has the same nameinfo()
.
function carInfo(car) {
car.info();
}
let car = new Car('Corolla', '2001', 4);
let sport = new SportsCar('Camaro', '2023', 6);
// Polimorphism
carInfo(car); // output: "Corolla, 2001, 4, Toyota, 1"
carInfo(sport); // output: "Camaro, 2023, 6, Toyota, 2"
In this way, polymorphism allows us to write more flexible and reusable code by creating classes that share a common interface but can have different implementations for their methods.