코틀린에서 클래스는 class 키워드로 선언된다.
class Person { /*...*/ }
클래스 선언은 클래스 이름, 클래스 헤더(유형 매개변수, 기본 생성자 및 기타 사항 지정) 및 중괄호로 묶인 클래스 본문으로 구성된다. 헤더와 본문은 모두 선택사항이다. 클래스에 본문이 없으면 중괄호를 생략할 수 있다.
class Empty
Constructors
코틀린에서 클래스는 기본 생성자와 하나 이상의 보조 생성자를 가질 수 있다. 기본 생성자는 클래스 헤더의 일부로 선언되며, 클래스 이름 뒤에 타입 매개변수와 함께 작성한다.
class Person constructor(firstName: String) { /*...*/ }
기본 생성자에 annotations이나, 접근 제한자(가시적 지정자, visibility modifiers)가 없으면 생성자 키워드를 생략할 수 있다.
class Person(firstName: String) { /*...*/ }
기본 생성자는 코드를 포함할 수 없다. 초기화 코드는 init 키워드가 접두사로 붙은 초기화 블록에 배치할 수 있다. 인스턴스를 초기화하는 동안, initialization 블록은 속성 initializers와, interleaved 된 클래스 본문에 나타나는 것과 동일한 순서로 실행된다.
기본 생성자에 포함된 매개변수는 초기화 블록과 클래스 본문에 선언된 속성 초기화에서 모두 사용이 가능하다.
class Customer(name: String) {
val customerKey = name.uppercase()
}
코틀린에서는 속성을 기본 생성자에서 선언하고 초기화할 수 있는 간결한 구문을 제공한다. 이와 같은 선언에서는 해당 속성의 기본 값도 지정할 수 있다.
class Person(val firstName: String, val lastName: String, var isEmployed: Boolean = true)
클래스 속성을 선언할 때 후행 쉼표를 사용할 수 있다.
class Person(
val firstName: String,
val lastName: String,
var age: Int, // trailing comma
) { /*...*/ }
기본 생성자에 선언된 속성은 일반 속성과 마찬가지로 var(변경가능) 또는 val(읽기전용)일 수 있다. 만약, 생성자에 annotations 또는 접근 제한자가 있는 경우, 생성자 키워드가 필요하고, 제한자를 그 앞에 붙여서 선언한다.
class Customer public @Inject constructor(name: String) { /*...*/ }
Secondary constructors
클래스는 constructor가 접두사로 붙는 보조 생성자를 선언할 수 있다.
class Person(val pets: MutableList<Pet> = mutableListOf())
class Pet {
constructor(owner: Person) {
owner.pets.add(this) // adds this pet to the list of its owner's pets
}
}
클래스에 기본 생성자가 있는 경우, 선언된 각 보조 생성자는 다른 보조 생성자를 통해 직접 또는 간접적으로 기본 생성자에 위임해야 한다. 동일한 클래스의 다른 생성자에 대한 위임은 this 키워드를 이용해서 수행한다.
class Person(val name: String) {
val children: MutableList<Person> = mutableListOf()
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
초기화 블록의 코드는 기본 생성자의 일부가 될 수 있는 효과적인 코드이다. 기본 생성자에 대한 위임은 보조 생성자의 항상 첫번째 명령문으로 수행되기 때문에 모든 초기화 블록 및 속성 초기화 코드는 보조 생성자의 본문보다 먼저 실행된다. 만약, 클래스에 기본 생성자가 없더라도 위임은 여전히 암시적으로 발생하고 초기화 블록은 계속 실행된다.
추상 클래스가 아닌 클래스가 생성자(기본 또는 보조)를 선언하지 않으면 인수 없이 기본 생성자가 생성되고 생성자의 가시성이 공개 된다. (기본이 public) 클래스에 공개 생성자가 포함되지 않도록 하려면 기본이 아닌 가시성을 가진 빈 기본 생성자를 선언해야된다.
class DontCreateMe private constructor () { /*...*/ }
❕JVM에서 모든 기본 생성자 매개변수에 기본 값이 있는 경우 컴파일러는 기본 값을 사용할 매개변수가 없는 추가 생성자를 새성한다. → 매개변수가 없는 생성자를 통해 클래스 인스턴스를 생성하는 Jackson 또는 JPA 라이브러리와 코틀린을 더 쉽게 사용 가능함.
class Customer(val customerName: String = "")
Creating instances of classes
클래스의 인스턴스를 생성하려면 일반적인 함수 호출처럼 생성자를 호출한다. → 코틀린에는 new 키워드가 없다.
val invoice = Invoice()
val customer = Customer("Joe Smith")
Class members
클래스의 멤버로 가능한 것
- 생성자와 초기화 블록
- 함수
- 속성
- 중첩 및 inner 클래스
- Object 선언
Abstract classes
클래스는 일부 또는 전체 구성원과 함께 abstract 키워드로 추상클래스로 선언될 수 있다. 추상 멤버는 해당 클래스에 구현부가 없다. open 키워드를 함수에 붙이거나 클래스에 주석을 달 필요가 없다.
abstract class Polygon {
abstract fun draw()
}
class Rectangle : Polygon() {
override fun draw() {
// draw the rectangle
}
}
추상 멤버가 아닌 open 키워드가 붙은 멤버를 추상 멤버로 오버라이딩 할 수 있다.
open class Polygon {
open fun draw() {
// some default polygon drawing method
}
}
abstract class WildShape : Polygon() {
// Classes that inherit WildShape need to provide their own
// draw method instead of using the default on Polygon
abstract override fun draw()
}
Companion Object
클래스의 인스턴스 없이 호출할 수 있지만 클래스 내부에 엑세스해야 하는 함수를 작성하는 경우 해당 클래스 내부의 object 선언의 멤버로 작성할 수 있다. → 자바의 static과 비슷하지만 엄연히 다름
클래스 내부에 companion object 키워드로 개체를 선언하면 클래스 이름을 한정자로 접근 가능하다.