본문 바로가기
Java & Kotlin/Kotlin

[Kotlin] 클래스를 다루는 방법

by heekng 2022. 7. 6.
반응형

클래스를 다루는 방법

클래스와 프로퍼티

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

class Person1 constructor(name: String, age: Int) {
    val name: String = name;
    var age: Int = age;
}

또는

class Person2(val name: String, var age: Int)
  • 코틀린에서는 필드만 만들면 getter, setter을 자동으로 만들어준다.
    • 때문에 이를 프로퍼티라 부른다.
    • 프로퍼티: 필드 + getter + setter
  • constructor은 생략할 수 있다.
  • .필드 를 이용해 gettersetter을 바로 호출한다.
    • 코틀린에서 자바 클래스를 사용하더라도 .필드getter, setter을 사용할 수 있다.

생성자와 init

Java

public class JavaPerson {

    private final String name;
    private int age;

    public JavaPerson(String name, int age) {
        if (age <= 0) {
            throw new IllegalArgumentException(String.format("나이는 %s일 수 없습니다.", age));
        }
        this.name = name;
        this.age = age;
    }

    public JavaPerson(String name) {
        this(name, 1);
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Kotlin

class Person3(val name: String, var age: Int) {

    init {
        if (age <= 0) {
            throw IllegalArgumentException("나이는 ${age}일 수 없습니다.")
        }
    }

    constructor(name: String) : this(name, 1)

    constructor(): this("홍길동")

}
  • init 블록: 클래스가 초기화되는 시점에 한 번 호출되는 블록
    • 값을 적절히 만들어주거나, validation 하는 로직이 들어간다.
  • constructor(name: String) : this(name, 1)형태로 새로운 생성자 생성이 가능하다.
  • 주 생성자(primary constructor): 기존에 최상단에 존재하던 생성자, 반드시 존재해야 하며 주 생성자에 파라미터가 하나도 없다면 생략 가능하다.
  • 부 생성자(secondary constructor): 있을 수도 있고, 없을 수도 있다. 바디를 가질 수 있다.
  • 하지만 코틀린에서는 기본적으로 부 생성자 보다 default parameter을 이용한다.
    • converting과 같은 경우 부 생성자를 사용할 수 있지만, 그보다는 정적 팩토리 메소드를 추천한다.

커스텀 getter, setter

class Person5(val name: String, var age: Int) {

    init {
        if (age <= 0) {
            throw IllegalArgumentException("나이는 ${age}일 수 없습니다.")
        }
    }

    /*
    fun isAdult(): Boolean {
        return this.age >= 20
    }
     */

    /*
    val isAdult: Boolean
        get() {
            return this.age >= 20
        }
     */

    val isAdult: Boolean
        get() = this.age >= 20
}
  • 위의 세가지 방법 모두 동일한 기능이고 표현 방법만 다르다.
    • byte 코드로 변경하여 확인할 수 있다.
  • isAdult라는 프로퍼티를 만들고, get() 메서드를 재 지정하여 사용하는 방식이다.
    • person.isAdult를 사용할 때 get()이 실행되는 방식!
    • 코틀린에서는 필드를 만들었을 때 getter, setter을 자동으로 만들어준다는 것을 활용하는 방식

backing field

Kotlin

class Person6(name: String = "heekng", var age: Int = 1) {

    val name = name
        get() = field.uppercase()

    val upperCaseName: String
        get() = this.name.uppercase()

}
  • name 필드의 getter을 재정의하고싶다면 위와 같이 get()을 재정의한다.
  • field: 예약어, 자기 자신
    • 만약 get()에 해당 필드(name)을 그대로 사용한다면 또 다시 name에 대한 get을 호출하기 때문에 무한루프가 발생한다.
반응형