Kotlin/Basic

Kotlin은 Java와 무엇이 다른가? (8) - 클래스

bongveloper 2024. 9. 19. 17:29

Class

Kotlin에서 클래스를 다룰 때에는 Java에 문법과 비슷하면서도 조금 다르다.

Kotlin에서 기본적으로 생성자를 만들 때에는 class 키워드를 사용한다.

class Person {
}

Constructor(생성자)와 Property(프로퍼티)

Kotlin에서 생성자를 만들 때에는 constructor 키워드를 사용한다.

class Person constructor(name: String,age: Int){
    var name: String = name,
    var age: Int = age
}

이 constructor 키워드는 생략이 가능한데, 생략하면 아래와 같이 사용 가능하다.

class Person (name: String,age: Int){
    var name: String = name,
    var age: Int = age
}

그리고 Property도 생략 가능하다. Property를 생략하면 아래와 같다.

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

Kotlin에서는 기본적으로 getter와 setter를 선언하지 않고 사용 가능하다.
그리고 Property이름으로 호출한다.

val person = Person("kibong", 30)
person.name
person.age
person.name = "kibong kim"
person.age = 31

Init, Secondary Constructors(보조 생성자)

init

Kotlin에서 주생성자에 처리할 로직이 필요한 경우에는 init을 사용한다.

class  Person(val name: String,  var age: Int)  {
    init  { 
        if  (age <  0  || age >  150)  { 
            throw  IllegalArgumentException("나이는 0에서 150 사이여야 합니다.") 
        }
    }
}

이렇게 예외 처리를 해야하거나 적절한 값을 넣어주어야 하는 경우에 자주 사용한다.

Secondary Constructors(부 생성자)

주 생성자 말고 부 생성자가 필요한 경우 constructor를 사용해서 보조 생성자 사용이 가능하다.
부 생성자는 아래와 같다.

class  Person(val name: String,  var age: Int)  {
    //1
    init  {     
        if  (age <  0  || age >  150)  { 
            throw  IllegalArgumentException("나이는 0에서 150 사이여야 합니다.") 
        }
    }

    //2
    constructor(name : String) : this(name, 30){

    }

    //3
    constructor() : this("kibong", 30){

    }
}

보조 생성자의 특징은 아래와 같다.

  • 주 생성자를 this로 호출할 것
  • 부 생성자는 body를 가질 수 있음
  • 호출 순서는 위에 코드에서 1,2,3 순서로 호출됨

하지만 보조 생성자를 사용하기보다는 Default Parameter를 사용하는 것이 좋다.
그 이유는 constructor를 계속해서 생성해주어야 하기 때문에 가독성이 좋아지지 않는다.
그리고 객체에서 객체로 변환할 때 쓰일 수도 있지만 그런 경우에도 사실 정적 팩토리 메서드 패턴을 쓰는 것이 더 좋다.

Custom Getter/Setter

Custom getter/setter는 프로퍼티처럼 취급하는 로직이 필요하거나 기본 getter에서 추가적인 로직이 필요한 경우 사용된다.

프로퍼티처럼 취급되는 경우

성인인지 검증하는 로직이 필요한 경우

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

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

    val isAdult : Boolean
        get() = this.age >= 20
}

이렇게 두 가지 경우로 로직을 작성할 수 있다.
두 개 다 Java코드로 변환하면 같은 로직이다.

그럼 두 가지 경우 중 어떤 것을 쓰는 것이 좋을까?

  • get()을 쓸 때에는 속성에 관련된 경우
  • 함수를 쓸 때에는 그 외에 것들을 쓸 때 쓰는 것이 좋다고 한다.

isAdult에 경우 age에 관련된 것이므로 get()을 쓰는 것이 조금 더 나은 코딩이라고 볼 수 있다.

getter에 추가적인 로직이 필요한 경우

자 getter에 추가적인 로직이 필요한 경우 get() 로직에 추가할 수 있는데

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

로도 사용이 가능하다.
이렇게 filed를 사용하는 것을 backing field라고 부르는데,
이렇게 사용하는 이유는 name을 호출하게 되면 무한루프가 돌게 되기 때문에 자기 자신을 나타내는 field를 사용하는 것이다.

Setter 사용은 권장하지 않는다.

요약

  • Kotlin에서는 constructor를 이용해서 생성자 생성이 가능하다.
  • 생성자 생성을 할 때에도 간단하게 생략하면서 사용 가능하다.
  • 주 생성자에 로직이 필요한 경우에는 init을 사용해서 로직을 추가 할 수 있다.
  • 부 생성자가 필요한 경우 constructor를 사용해서 생성 가능하다.
  • Kotlin에서 부 생성자보다는 Default Parameter나 정적 팩토리 메서드 패턴을 사용하는 것을 권장한다.
  • Custom Getter를 통해 프로퍼티처럼 취급하거나 객체의 필드에 로직을 추가하는 것이 가능하다.
  • Setter는 사용되는 것이 권장되지 않고 따로 커스텀하게 만드는 것을 권장한다.

출처 : 자바 개발자를 위한 코틀린 입문(Java to Kotlin Starter Guide)