ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 9강. 코틀린에서 클래스를 다루는 방법
    BackEnd/Kotlin 2024. 3. 3. 06:00
    반응형
    1. 클래스와 프로퍼티
    2. 생성자와 init
    3. 커스텀 getter, setter

     

    클래스와 프로퍼티

    • 프로퍼티(property) = 필드(field) + getter + setter

     

      다음은 개명이 불가능한 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으로 구현하면 다음과 같습니다. Kotlin에서는 필드만 만들면 getter, setter를 자동으로 만들어 줍니다. 그러므로 Kotlin에서는 프로퍼티라고 부릅니다.

    public class Person constructor(name: String, age: Int) {
      val name = name
      var age = age
    }
    • 접근 지시어, public은 생략 가능합니다.
    • constructor는 생략할 수 있습니다.
    • 클래스의 필드 선언과 생성자를 동시에 선언할 수 있습니다.
    • 클래스의 body에 아무 것도 없다면 생략 가능합니다.

      그러므로, 다음과 같이 간결하게 구현할 수 있습니다. 

    class Person(
      val name: String,
      var age: Int
    )

     

      getter, setter에 대한 호출은 .필드를 사용합니다. Kotlin에서 Java 클래스를 사용할 경우에도 .필드로 getter, setter를 사용합니다.

    val person = Person("Kotlin", 100)
    println(person.name) // getter
    person.age = 10      // setter
    println(person.age)

     

    생성자와 init

      다음은 클래스가 생성되는 시점에 나이를 검증하는 Java 코드입니다.

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

     

      Kotlin으로 구현하면 다음과 같습니다.

    class Person(
      val name: String,
      var age: Int
    ) {
      init {
        if (age <= 0) {
          throw IllegalArgumentException("나이는 ${age}일 수 없습니다.")
        }
      }
    }
    • init(초기화 블록):  클래스가 초기화되는 시점에 한 번 호출되는 블록입니다. 값을 적절히 만들어 주거나 validation 로직을 넣는 용도로 사용됩니다.

     

      다음은 새로운 생성자를 추가한 Java 코드입니다.

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

     

      Kotlin에서 새로운 생성자는 constructor 키워드와 함께 만들어져야 합니다.

    class Person(
      val name: String,
      var age: Int
    ) {                                          // primary constructor
      init {
        if (age <= 0) {
          throw IllegalArgumentException("나이는 ${age}일 수 없습니다.")
        }
        println("init block")
      }
      
      constructor(name: String) : this(name, 1) { // secondary constructor 
        println("secondary constructor")
      }
    }
    • constructor(파라미터)로 생성자를 추가합니다.
    • 클래스를 만들 때 함께 만들었던 생성자를 주생성자(primary constructor)라고 합니다.
    • 주생성자는 반드시 존재해야 합니다. 단, 주생성자에 파라미터가 하나도 없다면 생략 가능합니다.
    • 아래 있는 생성자를 부생성자(secondary constructor)라고 합니다. 부생성자는 있을 수도 있고 없을 수도 있습니다.
    • 부생성자는 최종적으로 주생성자를 this로 호출해야 합니다.
    • 부생성자는 body를 가질 수 있습니다.
    • 본문은 역순으로 실행됩니다. 즉, 부생성자를 통해 인스턴스를 생성하면 초기화 블록의 body가 먼저 호출됩니다.

      Kotlin에서는 다음과 같이 부생성자보다는 default parameter를 권장합니다. 또한, Converting과 같은 경우도 부생성자를 사용할 수 있지만, 그보다 정적 팩토리 메서드 사용을 권장합니다.

    class Person(
      val name: String = "Kotlin",
      var age: Int = 1,
    ) {                                          // primary constructor
      init {
        if (age <= 0) {
          throw IllegalArgumentException("나이는 ${age}일 수 없습니다.")
        }
      }
    }

     

    커스텀 getter, setter

      다음은 성인인지 확인하는 Java 코드입니다.

      public boolean isAdult() {
        return this.age >= 20;
      }

     

      Kotlin에서는 Java와 같이 함수로 구현할 수도 있고, 프로퍼티로도 구현할 수 있습니다.

        // Function
        fun isAdult(): Boolean {
            return this.age >= 20
        }
        
        // Custom getter
        val isAdult: Boolean
            get() = this.age >= 20
    
        val isAdult: Boolean
            get() {
                return this.age >= 20
            }

     

      Custom getter를 사용하면 자기 자신을 변형해 줄 수도 있습니다. 다음은 name을 get할 때 무조건 대문자로 바꾸어 주는 코드입니다.

    class Person(
        name: String,
        var age: Int
    ) {
        val name = name
            get() = field.uppercase()
    }
    • field: 자기 자신을 가리키는 예약어입니다. 보이지 않는 field라고 해서 backing field라고 부릅니다.

     

      다음은 Custom setter를 사용한 예제 코드입니다. name을 set할 때 무조건 대문자로 바꾸는 코드입니다.

    class Person(
        name: String,
        var age: Int
    ) {
        var name = name
            set(value) {
                field = value.uppercase()
            }
    }

     

    감사합니다.

    반응형

    댓글

Designed by Tistory.