클래스
Kotlin 에서 클래스는 class
키워드를 사용하여 정의합니다:
1class Person { /*...*/ }
2
클래스 정의는 클래스의 이름과 헤더(파라미터나 주생성자, 기타 다른 요소들), 그리고 중괄호로 감싸진 몸체로 구성됩니다. 헤더와 몸체는 선택적인 요소로, 클래스의 몸체가 없으면 중괄호는 생략될 수 있습니다.
1class Empty
2
생성자
Kotlin 에서 클래스는 주생성자와 하나 이상의 부생성자들을 가집니다. 주생성자는 클래스의 헤더의 이름 뒤에, 선택적인 타입 파라미터와 함께 정의됩니다.
1class Person constructor(firstName: String) { /*...*/ }
2
주생성자에 아무런 어노테이션도 없고 가시성 수정자가 없다면, constructor
키워드는 생략할 수 있습니다:
1class Person(firstName: String) { /*...*/ }
2
주생성자는 클래스의 인스턴스와 그의 프로퍼티들을 초기화하며, 어떠한 실행 가능한 코드를 포함할 수 없습니다.
오브젝트 생성 시 어떠한 코드를 실행해야 한다면, 클래스 몸체에 초기화 블럭을 사용하세요. 초기화 블럭은 init
키워드와 뒤따르는 중괄호로 정의됩니다.
그 중괄호 안에 실행하려는 코드를 작성하세요.
인스턴스의 초기화 중에, 초기화 불럭이 실행되며 그 순서는 사이사이에 끼어들 수 있는 프로퍼티 초기화 문장을 포함하여 클래스의 몸체에 정의된 순서를 따릅니다:
1class InitOrderDemo(name: String) {
2 val firstProperty = "First property: $name".also(::println)
3
4 init {
5 println("First initializer block that prints $name")
6 }
7
8 val secondProperty = "Second property: ${name.length}".also(::println)
9
10 init {
11 println("Second initializer block that prints ${name.length}")
12 }
13}
14
위의 코드는 아래처럼 출력합니다:
First property: hello
First initializer block that prints hello
Second property: 5
Second initializer block that prints 5
주생성자의 파라미터들은 초기화 블럭 안에서 사용할 수 있습니다. 물론 클래스 몸체에 있는 프로퍼티 초기화 구문에서도 사용할 수 있습니다.
1class Customer(name: String) {
2 val customerKey = name.uppercase()
3}
4
Kotlin 은 주생성자에서의 간결한 프로퍼티 선언과 초기화 구문을 가지고 있습니다:
1class Person(val firstName: String, val lastName: String, var age: Int)
2
주생성자 내의 프로퍼티에 기본값도 설정해줄 수 있습니다:
1class Person(val firstName: String, val lastName: String, var isEmployed: Boolean = true)
2
그리고 끝단 쉼표도 허용됩니다:
1class Person(
2 val firstName: String,
3 val lastName: String,
4 var age: Int, // trailing comma
5) { /*...*/ }
6
다른 일반적인 프로퍼티들과 동일하게, 주생성자의 프로퍼티들도 변경 가능하거나(var
) 변경 불가능(val
)할 수 있습니다.
주생성자가 가시성 수정자나 어노테이션을 가진다면, constructor
키워드가 반드시 필요하며 수정자들이 왼쪽에 표기됩니다:
1class Customer public @Inject constructor(name: String) { /*...*/ }
2
가시성 수정자 에 대해 더 알아보세요.
부생성자
클래스는 constructor
키워드를 접두사로 가지는 부생성자도 정의할 수 있습니다:
1class Person(val pets: MutableList<Pet> = mutableListOf())
2
3class Pet {
4 constructor(owner: Person) {
5 owner.pets.add(this) // adds this pet to the list of its owner's pets
6 }
7}
8
클래스가 주생성자를 가지면, 각 부생성자들은 주생성자의 역할을 직접적(주생성자를 직접)으로던 간접적(다른 부생성자를 통해)으로던 위임받아야합니다.
그렇게 하려면 this
키워드를 사용합니다:
1class Person(val name: String) {
2 val children: MutableList<Person> = mutableListOf()
3 constructor(name: String, parent: Person) : this(name) {
4 parent.children.add(this)
5 }
6}
7
초기화 블럭 안의 코드는 주생성자의 일부분이 됩니다. 주생성자로의 위임은 부생성자의 첫 문장 바로 직전에 실행되므로, 초기화 블럭이나 프로퍼티 초기화는 부생성자의 블럭보다 이전에 실행됩니다.
클래스가 주생성자를 가지지 않더라도, 위임은 여전히 암시적으로 발생하기 때문에 초기화 블럭도 적절히 실행됩니다.
1class Constructors {
2 init {
3 println("Init block")
4 }
5
6 constructor(i: Int) {
7 println("Constructor $i")
8 }
9}
10
위 코드의 출력은 아래와 같습니다:
Init block
Constructor 1
만약 비-추상적인 클래스가 아무런 생성자도 정의하지 않으면, 인수를 받지 않는 주생성자를 자동으로 생성합니다. 이 생성자의 가시성은 public 입니다.
만약 생성자가 공개되지 않기를 원한다면, 아래처럼 빈 주생성자를 정의하고 가시성 수정자를 추가해줄 수 있습니다:
1class DontCreateMe private constructor() { /*...*/ }
2
JVM 에서, 모든 생성자의 매개변수가 기본값을 가지면, 컴파일러가 '모든 기본값을 사용하고 아무런 인수도 받지 않는 생성자'를 추가적으로 생성합니다. 이는 Kotlin 을 Jackson 이나 JPA 등과 같이 매개변수가 없는 생성자로부터 인스턴스를 만들어내는 라이브러리들과 함께 사용하기 쉽게 합니다.
1class Customer(val customerName: String = "") 2
클래스의 인스턴스 만들기
클래스의 인스턴스를 만드려면, 생성자를 일반적인 함수인 것 처럼 호출합니다. 생성된 인스턴스를 변수에 할당할 수 있습니다.
1val invoice = Invoice()
2
3val customer = Customer("Joe Smith")
4
Kotlin 에는
new
키워드가 없습니다.
중첩되거나, 안쪽의(inner), 혹은 익명 클래스들의 생성 과정은 중첩된 클래스와 안쪽 클래스 에서 기술합니다.
클래스의 멤버
클래스는 아래 목록이 나열하는 것들을 포함할 수 있습니다:
물려받기
클래스들은 서로간에 파생될 수 있으며, 상속 계층을 형성할 수 있습니다. Kotlin 에서 상속에 대해 자세히 알아보세요.
추상 클래스
어떤 클래스는 몇몇, 혹은 전부의 멤버를 가지면서 동시에 abstract
로 선언될 수 있습니다.
추상적인 멤버는 그 클래스에 구현을 직접 포함하지 않습니다. 추상 클래스나 함수를 open
으로 표기하지 않아도 됩니다.
1abstract class Polygon {
2 abstract fun draw()
3}
4
5class Rectangle : Polygon() {
6 override fun draw() {
7 // draw the rectangle
8 }
9}
10
비 추상적인 open
멤버를 추상적인 멤버로 재정의할 수도 있습니다:
1open class Polygon {
2 open fun draw() {
3 // some default polygon drawing method
4 }
5}
6
7abstract class WildShape : Polygon() {
8 // Classes that inherit WildShape need to provide their own
9 // draw method instead of using the default on Polygon
10 abstract override fun draw()
11}
12
동반 오브젝트 (companion object)
클래스의 인스턴스 없이 쓸 수 있어야 하지만 클래스와 연관되어 사용되는 함수(팩토리 함수 같은)를 작성해아한다면, 해당 클래스 안에서 작성한 오브젝트 표현식과 선언 안쪽에 추가할 수 있습니다.
특히, 일반적인 클래스 안에 동반 오브젝트(companion object) 를 정의하면, 그 오브젝트의 멤버를 해당 클래스 이름만을 사용하여 접근할 수 있습니다.
이 페이지가 도움이 되셨다면, 원문 페이지에 방문해 엄지척을 해주세요!