231 lines
7.0 KiB
Markdown
231 lines
7.0 KiB
Markdown
# **코틀린 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` 접근 제어자** | 같은 패키지 + 하위 클래스 접근 가능 | 오직 하위 클래스만 접근 가능 |
|
|
|
|
코틀린은 **객체지향 프로그래밍을 더 간결하고 효율적으로 작성할 수 있도록 개선**된 언어다.
|
|
다음에는 어떤 개념을 비교해볼까? |