# **코틀린 vs 자바: 객체지향 프로그래밍(OOP) 비교**  

코틀린과 자바는 둘 다 객체지향 프로그래밍(OOP)을 지원하는 언어지만, 코틀린은 더 간결하고 유연한 문법을 제공한다.  
이번 글에서는 **클래스 선언, 생성자, 상속, 접근 제어자, 데이터 클래스, 객체 선언** 등을 중심으로 자바와 코틀린의 차이점을 비교하겠다.  

---

## **1. 클래스 선언 방식 차이**  

자바에서는 클래스를 선언할 때 `class` 키워드를 사용하고, **필드와 생성자를 분리**해서 작성하는 것이 일반적이다.  

### **자바의 클래스 선언**
```java
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }
}
```
### **코틀린의 클래스 선언**  
코틀린에서는 **주 생성자(Primary Constructor)**를 **클래스 헤더에 직접 정의**할 수 있다.  

```kotlin
class Person(val name: String, val age: Int)
```

> **차이점 요약:**  
> - **자바:** 필드, 생성자, 게터를 따로 작성해야 함.  
> - **코틀린:** `val` 또는 `var`을 사용하면 **자동으로 필드와 게터 생성**.  

---

## **2. 생성자 (Constructors)**  

자바에서는 **기본 생성자**와 **매개변수가 있는 생성자**를 따로 정의해야 한다.  

### **자바의 생성자 오버로딩**
```java
public class Car {
    private String model;

    public Car() {
        this.model = "Unknown";
    }

    public Car(String model) {
        this.model = model;
    }
}
```

코틀린에서는 **기본값을 지정**할 수 있어 생성자 오버로딩을 줄일 수 있다.  

### **코틀린의 기본값 제공 방식**
```kotlin
class Car(val model: String = "Unknown")
```

> **차이점 요약:**  
> - 자바는 **생성자 오버로딩**이 필요하지만,  
> - 코틀린은 **기본값을 제공하면 생성자 하나로 해결 가능**.  

---

## **3. 상속 (Inheritance)과 `open` 키워드**  

자바에서 클래스를 상속하려면 `extends` 키워드를 사용하고, **메서드 오버라이딩 시 `@Override`를 명시**해야 한다.  

### **자바의 상속**
```java
public class Animal {
    public void makeSound() {
        System.out.println("Some sound");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark!");
    }
}
```

코틀린에서는 클래스가 **기본적으로 `final`이므로 상속을 허용하려면 `open` 키워드를 붙여야 한다**.  

### **코틀린의 상속**
```kotlin
open class Animal {
    open fun makeSound() {
        println("Some sound")
    }
}

class Dog : Animal() {
    override fun makeSound() {
        println("Bark!")
    }
}
```

> **차이점 요약:**  
> - **자바:** 모든 클래스가 기본적으로 **상속 가능**(`final`이 아님).  
> - **코틀린:** 모든 클래스가 기본적으로 **`final`이며, 상속하려면 `open`을 붙여야 함**.  
> - **오버라이딩 시 자바는 `@Override` 사용**, 코틀린은 **`override` 키워드 필수**.  

---

## **4. 접근 제어자 (Access Modifiers)**  

자바와 코틀린 모두 **`public`, `protected`, `private`** 접근 제어자를 제공하지만,  
코틀린에는 **추가로 `internal`이 있다**.  

| 접근 제어자 | 자바 | 코틀린 |
|------------|------|--------|
| `public`   | 모든 곳에서 접근 가능 | 동일 |
| `protected` | 같은 패키지 + 하위 클래스에서 접근 가능 | 하위 클래스에서만 접근 가능 (패키지 무관) |
| `private` | 같은 클래스 내에서만 접근 가능 | 동일 |
| `default` (생략 시) | 같은 패키지 내에서 접근 가능 | `internal` (같은 모듈 내에서 접근 가능) |

### **코틀린의 `internal` 키워드**  
```kotlin
internal class InternalClass {
    fun greet() = "Hello"
}
```
> - `internal`은 **같은 모듈 내에서만 접근 가능**(자바에는 해당 없음).  

---

## **5. 데이터 클래스 (Data Class)**  

자바에서는 **`equals()`, `hashCode()`, `toString()` 메서드를 직접 구현**해야 한다.  

### **자바의 데이터 클래스를 수동 구현**
```java
public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        User user = (User) obj;
        return age == user.age && Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}
```

코틀린에서는 **`data` 키워드를 추가하는 것만으로 자동 생성**된다.  

### **코틀린의 데이터 클래스**
```kotlin
data class User(val name: String, val age: Int)
```
> **차이점 요약:**  
> - 자바에서는 `equals()`, `hashCode()`, `toString()`을 직접 작성해야 함.  
> - 코틀린에서는 `data class`만 선언하면 자동 생성됨.  

---

## **6. 싱글턴 (Singleton) 객체 선언**  

자바에서 싱글턴 패턴을 구현하려면 **`static` 키워드를 사용하거나, `enum`을 활용**해야 한다.  

### **자바의 싱글턴 패턴**
```java
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
```

코틀린에서는 **`object` 키워드를 사용하면 자동으로 싱글턴이 된다**.  

### **코틀린의 싱글턴**
```kotlin
object Singleton {
    fun greet() = "Hello"
}

println(Singleton.greet())  // Hello
```

> **차이점 요약:**  
> - 자바는 **싱글턴을 만들기 위해 보일러플레이트 코드 필요**.  
> - 코틀린은 `object`를 사용하면 자동으로 싱글턴 객체 생성됨.  

---

## **정리: 자바 vs 코틀린 OOP 차이점**  

| 기능 | 자바 | 코틀린 |
|------|------|--------|
| **클래스 선언** | 필드 + 생성자 + 게터 필요 | `class Person(val name: String)` |
| **생성자 오버로딩** | 여러 개의 생성자 정의 필요 | 기본값 사용 가능 |
| **상속** | 기본적으로 가능 (`final`을 붙여야 제한) | 기본적으로 `final`, `open`을 붙여야 상속 가능 |
| **데이터 클래스** | `equals()`, `hashCode()`, `toString()` 직접 구현 | `data class`로 자동 생성 |
| **싱글턴 패턴** | `static` 필드 사용 | `object` 키워드 사용 |
| **`protected` 접근 제어자** | 같은 패키지 + 하위 클래스 접근 가능 | 오직 하위 클래스만 접근 가능 |

코틀린은 **객체지향 프로그래밍을 더 간결하고 효율적으로 작성할 수 있도록 개선**된 언어다.  
다음에는 어떤 개념을 비교해볼까?