# Encapsulation and Abstraction

**Encapsulation:**

Encapsulation is one of the fundamental principles of object-oriented programming (OOP). It refers to the bundling of data (variables) and methods that operate on that data into a single unit known as a class. Encapsulation restricts direct access to some of an object's components and prevents the accidental modification of data.

**Abstraction:**

Abstraction is the process of hiding the complex reality while exposing only the necessary parts. In Java, abstraction is achieved through abstract classes and interfaces. An abstract class can have abstract (unimplemented) methods, providing a blueprint for its subclasses. Interfaces define abstract methods that implementing classes must provide.

#### Access Modifiers (public, private, protected):

**Access Modifiers:**

Access modifiers define the visibility and accessibility of classes, methods, and fields in Java. There are four types of access modifiers:

* **public:** Accessible from any class.
* **private:** Accessible only within the same class.
* **protected:** Accessible within the same package and subclasses.
* **default (no modifier):** Accessible within the same package.

#### Encapsulation and Getters/Setters:

**Encapsulation with Getters and Setters:**

Encapsulation can be implemented by making the instance variables private and providing public getter and setter methods to access and modify these variables, ensuring data integrity and security.

```java
class Car {
    private String brand;  // Private variable

    // Getter method
    public String getBrand() {
        return brand;
    }

    // Setter method
    public void setBrand(String brand) {
        this.brand = brand;
    }
}
```

In this example, `brand` is private, so it cannot be accessed directly from outside the class. The `getBrand()` method allows read access, and the `setBrand(String brand)` method allows modification while controlling the access to the `brand` variable.

#### Abstract Classes and Interfaces:

**Abstract Classes:**

Abstract classes are classes that cannot be instantiated and can contain abstract methods (methods without implementation). Abstract classes are useful for providing a common base for subclasses.

```java
abstract class Shape {
    abstract void draw();  // Abstract method without implementation

    void commonMethod() {
        System.out.println("This is a common method.");
    }
}
```

In this example, `Shape` is an abstract class with an abstract method `draw()`. Subclasses of `Shape` must provide an implementation for the `draw()` method.

**Interfaces:**

Interfaces in Java are similar to abstract classes, but they can only contain abstract methods and cannot have instance variables. Classes implement interfaces and provide implementations for all abstract methods declared in the interface.

```java
interface Drawable {
    void draw();  // Abstract method without implementation
}
```

In this example, `Drawable` is an interface with an abstract method `draw()`. Classes that implement the `Drawable` interface must provide an implementation for the `draw()` method.

#### Example Code:

```java
// Encapsulation and Abstraction
class BankAccount {
    private double balance;

    // Constructor
    public BankAccount(double balance) {
        this.balance = balance;
    }

    // Getter and Setter for balance
    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}

// Abstract Class
abstract class Shape {
    abstract void draw();  // Abstract method without implementation

    void commonMethod() {
        System.out.println("This is a common method.");
    }
}

// Interface
interface Drawable {
    void draw();  // Abstract method without implementation
}

public class Main {
    public static void main(String[] args) {
        // Encapsulation and Abstraction Example
        BankAccount account = new BankAccount(1000);
        System.out.println("Account Balance: $" + account.getBalance());

        // Abstract Class Example
        Shape shape = new Shape() {
            @Override
            void draw() {
                System.out.println("Drawing a shape.");
            }
        };
        shape.draw();  // Output: Drawing a shape.
        shape.commonMethod();  // Output: This is a common method.

        // Interface Example
        Drawable drawable = new Drawable() {
            @Override
            public void draw() {
                System.out.println("Drawing something.");
            }
        };
        drawable.draw();  // Output: Drawing something.
    }
}
```

In this example, we demonstrate encapsulation with the `BankAccount` class, abstraction with the `Shape` abstract class, and interfaces with the `Drawable` interface. Each concept is illustrated with an example class or interface and its usage in the `Main` class.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://muhammad-tri-wibowo.gitbook.io/java-tutorials/object-oriented-programming-oop/encapsulation-and-abstraction.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
