자바에서는 클래스를 만들 때 필드(Field), 생성자(Constructor), Getter/Setter를 모두 작성해야 하지만, 코틀린은 이를 프로퍼티(Property)라는 개념으로 통합하여 한 줄로 해결한다.
코틀린은 클래스 이름 바로 옆에 생성자를 정의하는 주 생성자(Primary Constructor) 방식을 사용한다.
// 코틀린: 단 한 줄로 필드 생성, 생성자, Getter/Setter까지 해결
class User(val name: String, var age: Int)
// 자바였다면?
/*
public final class User {
private final String name;
private int age;
public User(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; }
}
*/
코틀린에서는 클래스의 필드를 프로퍼티라고 부른다.
val 프로퍼티: 내부적으로 private 필드 + public Getter를 생성한다.
var 프로퍼티: 내부적으로 private 필드 + public Getter + public Setter를 생성한다.
사용할 때는 자바처럼 .getName()을 호출할 필요 없이 점(.) 연산자로 바로 접근한다.
val user = User("John Doe", 20)
println(user.name) // 내부적으로 getName() 호출
user.age = 21 // 내부적으로 setAge() 호출
기본적인 Getter/Setter 외에 특정한 로직이 필요할 때 직접 정의할 수 있다. 이때 실제 값을 담고 있는 field (Backing Field)라는 키워드를 사용한다.
class Person(var name: String) {
var nickname: String = ""
set(value) {
// 입력값을 대문자로 바꿔서 저장하는 로직
field = value.uppercase()
}
val isAdult: Boolean
get() = this.age >= 20 // 별도의 필드 없이 계산된 값만 반환 (Custom Getter)
}
주 생성자에는 코드를 작성할 공간이 없다. 만약 객체가 생성되는 시점에 로직을 실행하고 싶다면 init 블록을 사용한다.
class Student(val name: String) {
init {
println("학생 객체가 생성되었습니다: $name")
require(name.isNotEmpty()) { "이름은 비어있을 수 없습니다." }
}
}
데이터를 담는 것이 목적인 클래스라면 data 키워드만 붙여보자. toString(), equals(), hashCode(), copy() 등을 컴파일러가 자동으로 만들어준다. (자바의 Record와 유사)
data class Book(val title: String, val author: String)
val book1 = Book("Kotlin", "JetBrains")
println(book1) // Book(title=Kotlin, author=JetBrains) 가 예쁘게 출력됨