# Activity 10: Object-Oriented Programming OOP in TypeScript

### 1\. **Class and Object**

* **Definition**:
    
    * A class is a blueprint for creating objects that share similar properties and methods.
        
    * An object is an instance of a class, containing actual values for the defined properties and behavior of the class.
        
* **Key Features**:
    
    * Classes define the structure of objects through properties and methods.
        
    * Objects are instantiated from classes and can have unique property values.
        
* **Implementation in TypeScript**:
    
    * Classes are defined using the `class` keyword, and objects are created with the `new` keyword.
        
* **Example Code**:
    
    ```typescript
    class Car {
        model: string;
        year: number;
    
        constructor(model: string, year: number) {
            this.model = model;
            this.year = year;
        }
    
        displayInfo(): void {
            console.log(`Model: ${this.model}, Year: ${this.year}`);
        }
    }
    
    // Creating an object
    const myCar = new Car('Toyota', 2020);
    myCar.displayInfo();  // Output: Model: Toyota, Year: 2020
    ```
    
* ### 2\. **Encapsulation**
    
* **Definition**: Encapsulation is the practice of hiding the internal state of an object and only exposing a controlled interface.
    
* **Key Features**:
    
    * Use access modifiers like `public`, `private`, and `protected` to control the visibility of class members.
        
    * **Public**: accessible from anywhere.
        
    * **Private**: accessible only within the class.
        
    * **Protected**: accessible within the class and subclasses.
        
* **How it’s Implemented in TypeScript**: TypeScript uses these access modifiers to define encapsulation.
    
* **Example**:
    
    ```typescript
    class Car {
      private speed: number;
    
      constructor() {
        this.speed = 0;
      }
    
      public accelerate(amount: number): void {
        this.speed += amount;
      }
    
      public getSpeed(): number {
        return this.speed;
      }
    }
    
    const car = new Car();
    car.accelerate(20);
    console.log(car.getSpeed()); // Output: 20
    // car.speed = 50; // Error: Property 'speed' is private and only accessible within the class 'Car'.
    ```
    

### 3\. **Inheritance**

* **Definition**: Inheritance allows a class to inherit properties and methods from another class.
    
* **Key Features**:
    
    * Promotes code reusability.
        
    * The `extends` keyword is used for inheritance in TypeScript.
        
    * **Super** is used to call the parent class constructor and methods.
        
* **How it’s Implemented in TypeScript**: A subclass extends a parent class, inheriting its properties and methods.
    
* **Example**:
    
    ```typescript
    class Animal {
      name: string;
    
      constructor(name: string) {
        this.name = name;
      }
    
      makeSound() {
        return `${this.name} makes a sound.`;
      }
    }
    
    class Dog extends Animal {
      constructor(name: string) {
        super(name); // Call the parent class constructor
      }
    
      makeSound() {
        return `${this.name} barks.`;
      }
    }
    
    const dog = new Dog("Rex");
    console.log(dog.makeSound()); // Output: Rex barks.
    ```
    

### 4\. **Polymorphism**

* **Definition**: Polymorphism allows objects of different types to be treated as instances of the same parent class.
    
* **Key Features**:
    
    * Method Overloading (compile-time polymorphism) and Method Overriding (runtime polymorphism).
        
* **How it’s Implemented in TypeScript**: TypeScript supports method overriding but does not directly support method overloading in the traditional sense. However, we can achieve overloading through function signatures.
    
* **Example**:
    
    ```typescript
    class Shape {
      area(): number {
        return 0;
      }
    }
    
    class Circle extends Shape {
      radius: number;
    
      constructor(radius: number) {
        super();
        this.radius = radius;
      }
    
      area(): number {
        return Math.PI * this.radius ** 2;
      }
    }
    
    class Rectangle extends Shape {
      width: number;
      height: number;
    
      constructor(width: number, height: number) {
        super();
        this.width = width;
        this.height = height;
      }
    
      area(): number {
        return this.width * this.height;
      }
    }
    
    const shapes: Shape[] = [new Circle(5), new Rectangle(4, 6)];
    shapes.forEach(shape => console.log(shape.area()));
    ```
    
* ### 5\. **Abstraction**
    
    * **Definition**: Abstraction is the process of hiding the implementation details and showing only the essential features of an object.
        
    * **Key Features**:
        
        * Abstract classes and interfaces are used to achieve abstraction.
            
    * **How it’s Implemented in TypeScript**: Abstract classes define methods without implementation, while interfaces define the structure without any implementation.
        
    * **Example**:
        
        ```typescript
        abstract class Employee {
          constructor(public name: string) {}
          abstract calculateSalary(): number;
        }
        
        class FullTimeEmployee extends Employee {
          calculateSalary(): number {
            return 50000;
          }
        }
        
        class PartTimeEmployee extends Employee {
          calculateSalary(): number {
            return 20000;
          }
        }
        
        const emp1 = new FullTimeEmployee("John");
        const emp2 = new PartTimeEmployee("Jane");
        console.log(emp1.calculateSalary()); // Output: 50000
        console.log(emp2.calculateSalary()); // Output: 20000
        ```
        
    
    ### 6\. **Interfaces**
    
    * **Definition**: An interface in TypeScript defines the structure of an object without specifying implementation details.
        
    * **Key Features**:
        
        * Used to define contracts that classes must follow.
            
        * Allows multiple classes to implement the same interface.
            
    * **How it’s Implemented in TypeScript**: Interfaces are defined using the `interface` keyword.
        
    * **Example**:
        
        ```typescript
        interface Flyable {
          fly(): void;
        }
        
        class Bird implements Flyable {
          fly() {
            console.log("The bird is flying.");
          }
        }
        
        class Plane implements Flyable {
          fly() {
            console.log("The plane is flying.");
          }
        }
        
        const bird = new Bird();
        bird.fly(); // Output: The bird is flying.
        const plane = new Plane();
        plane.fly(); // Output: The plane is flying.
        ```
        
        ### 7\. **Constructor Overloading**
        
        * **Definition**: Constructor overloading allows a class to have multiple constructor signatures.
            
        * **How it’s Implemented in TypeScript**: TypeScript achieves constructor overloading using optional parameters.
            
        * **Example**:
            
            ```typescript
            class Box {
              width: number;
              height: number;
            
              constructor(width?: number, height?: number) {
                this.width = width || 0;
                this.height = height || 0;
              }
            }
            
            const box1 = new Box();
            const box2 = new Box(10, 20);
            console.log(box1); // Output: Box { width: 0, height: 0 }
            console.log(box2); // Output: Box { width: 10, height: 20 }
            ```
            
    * ### 8\. **Getters and Setters**
        
        * **Definition**: Getters and setters provide methods to access and update private properties of a class.
            
        * **Key Features**:
            
            * **Get** allows read-only access.
                
            * **Set** allows controlled modification of a property.
                
        * **How it’s Implemented in TypeScript**: Getters and setters are defined using `get` and `set` keywords.
            
        * **Example**:
            
            ```typescript
            class Person {
              private _age: number;
            
              constructor(age: number) {
                this._age = age;
              }
            
              get age(): number {
                return this._age;
              }
            
              set age(value: number) {
                if (value < 0) {
                  throw new Error("Age cannot be negative.");
                }
                this._age = value;
              }
            }
            
            const person = new Person(25);
            console.log(person.age); // Output: 25
            person.age = 30;
            console.log(person.age); // Output: 30
            // person.age = -5; // Error: Age cannot be negative.
            ```
            
            These are the core OOP concepts as implemented in TypeScript, using its features like strong typing and access modifiers to enhance traditional OOP practices.
