☕️ Kotlin의 클래스 다루기
1. 클래스와 프로퍼티
Java에서 데이터 클래스를 만들려면 필드, 생성자, getter, setter 등 많은 보일러플레이트 코드가 필요하다.
Java 예시
public class JavaPerson { private final String name; private int age; public JavaPerson(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Kotlin은 프로퍼티(Property) 개념을 통해 이를 간결하게 만들 수 있다.
프로퍼티(Property) = 필드(Field) + 접근자(Getter/Setter)
Kotlin 예시
val은 getter만,var는 getter와 setter를 모두 자동으로 생성한다.// 1단계: 기본 구조 class Person constructor(name: String, age: Int) { val name: String = name var age: Int = age } // 2단계: 프로퍼티를 주 생성자에서 바로 선언 (가장 흔한 방식) // 'constructor' 키워드와 클래스 바디 '{}'도 내용이 없으면 생략 가능 class Person2(val name: String, var age: Int)사용법
Kotlin은 프로퍼티에 직접 접근하는 것처럼 보이지만, 실제로는 자동으로 생성된 getter와 setter를 호출한다.val person = Person2("김태일", 100) println(person.name) // person.getName() 호출 person.age = 10 // person.setAge(10) 호출
2. 생성자와 init
클래스 초기화 시점의 로직을 처리하는 방법.
주 생성자(Primary Constructor)와 init 블록
Java: 생성자 내에서 유효성 검증과 같은 로직을 수행한다.
public JavaPerson(String name, int age) { if (age <= 0) { throw new IllegalArgumentException("나이는 0보다 작을 수 없습니다."); } this.name = name; this.age = age; }Kotlin: 주 생성자에서는 코드를 직접 실행할 수 없으므로,
init블록을 사용한다.init블록은 객체가 생성될 때 주 생성자 실행 직후 호출된다.class Person3(val name: String, var age: Int) { init { if (age <= 0) { throw IllegalArgumentException("나이는 ${age}일 수 없습니다.") } println("초기화 블록") } }
부 생성자(Secondary Constructor)
Java:
this()를 사용하여 다른 생성자를 호출하는 오버로딩을 사용한다.public JavaPerson(String name) { this(name, 1); // 다른 생성자 호출 }Kotlin:
constructor키워드로 부 생성자를 정의하며, 반드시this()를 통해 주 생성자나 다른 부 생성자를 호출해야 한다.class Person3(val name: String, var age: Int) { // ... init 블록 ... // 부 생성자 constructor(name: String) : this(name, 1) { println("부 생성자 1") } }권장사항: Kotlin에서는 부 생성자를 만드는 것보다 Default Parameter를 사용하는 것을 더 권장한다. 변환 로직이 필요하다면 정적 팩토리 메서드 패턴을 고려하는 것이 좋다.
3. 커스텀 Getter, Setter와 Backing Field
프로퍼티의 접근자를 직접 구현할 수 있다.
커스텀 Getter
isAdult와 같이 기존 프로퍼티를 가공하여 새로운 값을 제공하고 싶을 때 사용한다.
Java: 별도의 메서드로 구현.
public boolean isAdult() { return this.age >= 20; }Kotlin: 함수로 만들거나, 커스텀 getter를 사용해 프로퍼티처럼 만들 수 있다.
class Person5(val name: String, var age: Int) { // 1. 함수로 구현 fun isAdultFunc(): Boolean { return this.age >= 20 } // 2. 커스텀 Getter를 사용한 프로퍼티 val isAdult: Boolean get() = this.age >= 20 // get() { return this.age >= 20 } 와 동일 }권장사항: 해당 객체의 속성으로 판단되면 커스텀 Getter를, 행위로 판단되면 함수를 사용하는 것이 좋다. (
person.isAdultvsperson.isAdultFunc())
Backing Field
커스텀 getter/setter 내부에서 프로퍼티 자기 자신을 참조하면 무한 루프에 빠지게 된다. (name의 getter가 name을 호출하고, 그 호출이 다시 getter를 부르는 식)
이를 방지하기 위해, 자기 자신을 가리키는 보이지 않는 필드인 field 라는 예약어를 사용하는데, 이를 Backing Field라고 한다.
class Person5(name: String, var age: Int) {
val name: String = name
get() = field.uppercase() // field는 name의 backing field를 의미
var ageWithOffset: Int = age
set(value) {
// setter의 파라미터는 관례적으로 value를 사용
field = value + 10 // field는 ageWithOffset의 backing field
}
}
✨ 최종 정리
- Kotlin에서는 필드를 만들면 getter와 (필요에 따라) setter가 자동으로 생기는데, 이를 프로퍼티(Property)라고 부른다.
- Kotlin의 클래스는 주 생성자(Primary Constructor)가 필수이며, 클래스 선언부에 위치한다. (단, 파라미터가 없다면 생략 가능)
constructor키워드로 부생성자(Secondary Constructor) 를 추가할 수 있지만, 그보다는 Default Parameter나 정적 팩토리 메서드를 권장한다.- 실제 메모리에 필드가 존재하지 않더라도, 계산된 값을 제공하는 커스텀 Getter를 만들 수 있다.
- 커스텀 getter/setter에서 무한 루프를 막기 위해
field라는 키워드를 사용하며, 이를 Backing Field라고 부른다.
'kotlin' 카테고리의 다른 글
| [Kotlin] 접근 제어 (0) | 2025.08.11 |
|---|---|
| [Kotlin] 상속 (3) | 2025.08.10 |
| [Kotlin] 예외 다루기 (1) | 2025.08.04 |
| [Kotlin] 함수 다루기 (0) | 2025.08.04 |
| [Kotlin] 반복문 (1) | 2025.08.04 |