코틀린 Classes

김성준·2022년 4월 25일
0

Kotlin

목록 보기
8/17

Classes(클래스)

코틀린에서 클래스의 선언은 class 키워드를 사용합니다.

class Person {/*...*/}

클래스는 클래스의 이름, (매개변수, 주 생성자 등을 지정하는)헤더, 중괄호로 둘러쌓인 바디로 이루어져 있습니다. 바디와 헤더는 둘 다 선택적입니다. 만약 바디가 없다면 중괄호는 생략될 수 있습니다.

class Empty

Constructors(생성자)

코틀린에서 클래스는 주생성자와 하나 혹은 그 이상의 보조 생성자를 가질 수 있습니다. 주생성자는 클래스 헤더의 일부분이고 클래스의 이름과 매개변수 뒤에 위치합니다.

class Person constructor(firstName: String) { /*...*/ }

만약 주생성자가 어떠한 어노테이션이나 접근 변경자가 없다면 constructor 키워드는 생략할 수 있습니다.

class Person(firstName: String) { /*...*/ }

주생성자는 어떠한 코드를 포함할 수 없습니다. 초기화에 대한 코드는 init 키워드를 사용하는 초기화 블럭에 작성되어야 합니다.

인스턴스가 만들어질 때, init 블럭은 클래스의 바디에 작성된 순서로 실행됩니다.

class InitOrderDemo(name: String) {
    val firstProperty = "First property: $name".also(::println)
    
    init {
        println("First initializer block that prints $name")
    }
    
    val secondProperty = "Second property: ${name.length}".also(::println)
    
    init {
        println("Second initializer block that prints ${name.length}")
    }
}

주생성자의 매개변수는 초기화 블럭에서 사용될 수 있습니다. 또한 클래스 바디 내에서 직접 프로퍼티를 초기화 하는데도 사용될 수 있습니다.

class Customer(name: String) {
    val customerKey = name.uppercase()
} 

코틀린은 주생성자에서 프로퍼티를 선언하고 초기화하는 간결한 문법도 제공합니다.

class Person(val fisrtName: String, val lastName: String, var age: Int)

이러한 방식으로 디폴트 값을 갖는 프로퍼티도 선언할 수 있습니다.

class Person(val fisrtName: String, val lastName: String, var age: Int, var imployed: Boolean = true)

클래스 프로퍼티를 선언할 때, trailing comma를 사용할 수도 있습니다.

class Person(
    val firstName: String,
    val lastName: String,
    var age: Int, // trailing comma
) { /*...*/ }

만약 생성자가 접근 변경자나 어노테이션을 갖는다면, constructor 키워드를 반드시 접근 변경자나 어노테이션 앞에 붙여줘야 합니다.

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)
    }
}

초기화 블록의 코드는 효과적으로 기본 생성자의 일부가 됩니다. 기본 생성자에 대한 위임은 보조 생성자의 첫 번째 명령문으로 발생하므로 모든 초기화 블록 및 프로퍼티 초기화 코드는 보조 생성자의 본문보다 먼저 실행됩니다.

비록 기본 생성자가 없다고 할지라도, 위임은 여전히 발생합니다. 따라서 init블럭은 실행됩니다.

class Constructors {
    init {
        println("Init block")
    }

    constructor(i: Int) {
        println("Constructor $i")
    }
}

만약 추상클래스가 아닌 클래스가 생성자를 선언하지 않으면 인자가 없는 원시 생성자가 만들어집니다. 그 생성자는 항상 public입니다.

만약 public 생성자가 없는 클래스를 만들고 싶다면, private인 비어있는 원시 생성자를 만들면 됩니다.

class DontCreateMe private constructor () { /*...*/ }

Creating instances of classes

클래스의 인스턴스를 만들기 위해서, 일반적인 함수처럼 생성자를 호출하면 됩니다.

val invoice = Invoice()

val customer = Customer("Joe Smith")

코틀린은 new 키워드가 존재하지 않습니다.

Class members

클래스는 아래의 목록에 있는것을 멤버로 포함할 수 있습니다.

Abstract classes(추상 클래스)

클래스는 abstract 키워드와 함께 선언될 수 있습니다. 또한 클래스의 멤버들도 abstract 키워드와 함께 쓸 수 있습니다.

abstract 멤버들은 클래스 내부에 구현하지 않습니다. 또한 이 멤버들에 open 지시자를 붙여주지 않아도 됩니다.

abstract class Polygon {
    abstract fun draw()
}

class Rectangle : Polygon() {
    override fun draw() {
        // draw the rectangle
    }
}

abstract가 아닌 open 멤버를 abstract 멤버로 override할 수 있습니다.

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 objects

클래스 인스턴스 없이 호출할 수 있지만 클래스의 내부에 액세스해야 하는 함수를 작성해야 하는 경우(예: 팩토리 메소드), 해당 클래스 내부의 object declaration 멤버로 작성할 수 있습니다.

더 구체적으로 말하자면, 클래스 내부에 companion object를 선언하면 클래스 이름만 한정자로 사용하여 해당 멤버에 액세스할 수 있습니다.

출처

코틀린 공식 문서

profile
수신제가치국평천하

0개의 댓글

관련 채용 정보