# SE1EP2 - Object Oriented Programming

# References

# Object Oriented Programming (OOP)

# - Mengenal OOP

Object Oriented Programming (OOP) adalah model pemrograman komputer yang mengatur desain perangkat lunak seputar data, objek, fungsi dan logika. Objek dapat didefinisikan sebagai susunan data yang memiliki atribut dan perilaku unik.

Beberapa komponen OOP yang umum di berbagai bahasa program adalah:

  • Object atau Class
  • Inheritance
  • Interface
  • Overriding
  • Overloading
  • Encapsulation

# - Inner Class

Java memungkinkan untuk mendefinisikan class dalam class atau biasa disebut dengan inner class.

Contoh inner class:

class App {

    public static void main(String[] args) {
        App.InnerApp inner = new App.InnerApp();
        inner.sayHello();
    }

    static class InnerApp {
        public void sayHello() {
            System.out.println("Hello World!");
        }
    }
}

# - Inheritance

Inheritance yang berarti pewarisan, sesuai dengan namanya yaitu sebuah konsep penurunan prilaku dari parent class kepada child class.

Contoh Inheritance:

class Vehicle {

    String name;
}

class Car extends Vehicle {

    Car(String name) {
        this.name = name;
    }
}

class App {
    
    public static void main(String[] args) {
        Car car = new Car("minibus");
        System.out.println(car.name);
    }
}

# - Overriding

Overriding adalah suatu konsep untuk merubah prilaku dari parent class.

Contoh overriding:

class Vehicle {

    String name;

    String getFuelType() {
        return "stone";
    }
}

class Car extends Vehicle {

    Car(String name) {
        this.name = name;
    }

    @Override
    String getFuelType() {
        return "gas";
    }
}

class App {
    
    public static void main(String[] args) {
        Car car = new Car("minibus");
        System.out.println(car.getFuelType());
    }
}

# - Overloading

Overloading pada dasarnya mirip dengan Overriding, hanya saja Overloading dapat merubah parameter dari method aslinya.

Contoh overloading:

class Vehicle {

    String name;

    String getFuelType() {
        return "stone";
    }

    void run() {
        System.out.println(this.name + " is running");
    }
}

class Car extends Vehicle {

    Car(String name) {
        this.name = name;
    }

    @Override
    String getFuelType() {
        return "gas";
    }

    void run(int speedKmph) {
        System.out.print("Speed " + speedKmph + " km/h. ");
        super.run();
    }
}

class App {
    
    public static void main(String[] args) {
        Car car = new Car("minibus");
        car.run(12);
    }
}

# - Interface

Interface adalah blueprint dari sebuah class. Interface tidak dapat di eksekusi secara langsung, tetapi hanya bisa di implementasi oleh class lainnya. Interface tidak mendukung property atau attribute dan setiap method tidak memiliki body.

Contoh Interface:

interface Vehicle {
    
    public String getFuelType();
}

class Car implements Vehicle {

    public String getFuelType() {
        return "gas";
    }
}

class App {

    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.getFuelType());
    }
}

# - Abstraction

Abstraction merupakan sebuah konsep abstraksi yang berupa class dan hampir mirip dengan interface, hanya saja sebuah Abstract class tidak dapat dipanggil secara langsung, tetapi harus melalui child class. Abstract method pada abstract class tidak boleh menggunakan body dan dan harus di override.

Contoh Abstract Class:

abstract class Vehicle {

    public abstract String getFuelType();

    public void run() {}
}

class Car extends Vehicle {

    public String getFuelType() {
        return "gas";
    }
}

class App {

    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.getFuelType());
    }
}

# - Modifiers

Modifiers pada java berfungsi untuk menentukan bagaimana sebuah class atau method dapat di implementasikan. Contoh saat kita ingin membuat sebuah method yang hanya dapat di akses oleh class tertentu saja, kita bisa menggunakan modifier protected.

Modifiers pada java dapat diterapkan untuk Class, Attribute dan Method. Berikut ini table Java Modifiers sesuai penempatan dan fungsinya:

Modifiers:

Position Modifiers Type Role
class public Access dapat diakses dimanapun
class default Access hanya dapat diakses pada package yang sama
attributes, methods, constructors public Access dapat diakses dimanapun
attributes, methods, constructors private Access hanya dapat diakses dalam class yang sama
attributes, methods, constructors default Access hanya dapat di akses pada package yang sama
attributes, methods, constructors protected Access dapat diakses oleh package yang sama atau subclass
class final Non-Access tidak dapat di override
class abstract Non-Access hanya dapat di akses pada subclass
attributes, methods final Non-Access tidak dapat di override
attributes, methods static Non-Access hanya dapat diakses diluar instance
methods abstract Non-Access hanya dapat di akses pada subclass yang mengimplementasi
attributes transient Non-Access diabaikan saat proses serialisasi (object serialization)
methods synchronized Non-Access hanya dapat di akses dalam satu thread sekali eksekusi
methods volatile Non-Access selalu menggunakan memori utama atau memori fisik bukan cached

# - Encapsulation

Encapsulation pada OOP adalah sebuah mekanisme pembungkusan komponen seperti property (attributes) dan fungsi (method) dalam satu kesatuan. Pada encapsulation, setiap property dan method dapat disembunyikan dan hanya dapat diakses oleh class terpilih. Konsep tersebut dikenal juga dengan Access Visibility atau Modifiers.

Access Modifiers yang didukung oleh Java:

Access Modifier Class Package Subclass Global
Private
Default
Protected
Public

Contoh Private Modifier:

package com.example.vehicle;

class Vehicle {

    private String getFuelType() {
        return "stone";
    }
}

Contoh Default Modifier:

package com.example.vehicle;

class Vehicle {

    String getFuelType() {
        return "stone";
    }
}

class Car {

    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        System.out.println(vehicle.getFuelType());
    }
}

Contoh Protected Modifier:

package com.example.vehicle;

class Vehicle {

    protected String getFuelType() {
        return "stone";
    }
}

class Car extends Vehicle {

    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.getFuelType());
    }
}

Contoh Public Modifier:

// Vehicle.java
package com.example.vehicle;

public class Vehicle {

    public String getFuelType() {
        return "stone";
    }
}

// App.java
package io.example;

import com.example.vehicle.Vehicle;

class App {

    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        System.out.println(vehicle.getFuelType());
    }
}

# - Generics

Generics atau Parameterized Types pada Java mengacu pada susunan object yang dapat menampung Non-Primitive Data Type (String, Long, Integer dll) sebagai parameternya. Setiap parameter yang bersifat generic dapat dideklarasikan dengan satu karakter Alfabet.

Contoh deklarasi Generics:

class Factory<T> {

    T buyNew(Class<T> c) throws Exception {
        // deprecated
        // return c.newInstance();
        return c.getDeclaredConstructor().newInstance();
    }
}

class Car {

    String getFuelType() {
        return "gas";
    }
}

class App {

    public static void main(String[] args) throws Exception {
        Factory<Car> factory = new Factory<Car>();
        Car myCar = factory.buyNew(Car.class);

        System.out.println(myCar.getFuelType());
    }
}

# - Object Iteration

Object Iteration adalah perulangan pada sekumpulan object atau class.

Terdapat beberapa class yang dapat menampung kumpulan object atau bisa kita sebut dengan collection. Beberapa class yang umum digunakan untuk menampung kumpulan object yaitu:

class keterangan
java.util.ArrayList Menyimpan data berupa array
java.util.HashMap Menyimpan data berupa map (Key, Value)

Contoh penggunaan ArrayList:

import java.util.ArrayList;
import java.util.Iterator;

class Car {
    String name;

    Car(String name) {
        this.name = name;
    }
}

class App {

    public static void main(String[] args) {

        ArrayList<Car> cars = new ArrayList<>();

        cars.add(new Car("minibus"));
        cars.add(new Car("sedan"));
        cars.add(new Car("bus"));
        cars.add(new Car("truck"));

        System.out.println("Using for loop:");

        for (int i = 0; i < cars.size(); i++) {
            Car car = cars.get(i);
            System.out.println(car.name);
        }


        System.out.println("-------------------");
        System.out.println("Using for each loop:");

        for (Car car: cars) {
            System.out.println(car.name);
        }

        
        System.out.println("-------------------");
        System.out.println("Using iterator:");

        Iterator<Car> carsIt = cars.iterator();

        while (carsIt.hasNext()) {
            Car car = carsIt.next();
            System.out.println(car.name);
        }
    }
}

Contoh penggunaan java.util.HashMap:

import java.util.HashMap;
import java.util.Map;

class Car {
    String name;

    Car(String name) {
        this.name = name;
    }
}

class App {

    public static void main(String[] args) {
        HashMap<String, Car> cars = new HashMap<>();

        cars.put("minibus", new Car("minibus"));
        cars.put("sedan", new Car("sedan"));
        cars.put("bus", new Car("bus"));
        cars.put("truck", new Car("truck"));

        for (Map.Entry<String, Car> item: cars.entrySet()) {
            Car car = item.getValue();
            System.out.println(String.format("Key: %s, Value: %s", item.getKey(), car));
        }
    }
}