You will be fine

<Kotlin> 2. 코틀린 vs 자바 클래스 스타일 비교

by BFine
반응형

가.  클래스

 a.  final을 좋아하는 코틀린

  -   간단하게 코틀린 클래스를 생성하고 디컴파일 해보자!

  -  클래스를 보면 final 키워드가 붙은 것을 볼 수 있다. 여기서 알 수 있듯이 코틀린은 거의 대부분 final 이 기본이다.

  -  아시다시피 클래스에 final이 붙어있으면 상속이 불가능하다.! 개인적으로 코틀린은 확장에 대해서 제어하는 듯한 느낌을 받았다.

   => 여담이지만 최근에 코드리뷰 받으면서 알게 되었는데 lombok에 보면 @UtiltyClass가 있다. 주석을 보면 자동으로 클래스에 final을 붙여주고

        private 생성자를 만들어주고 등등.. 써져있었다.  부끄럽지만 그때 클래스에 final 붙이면 어떻게 되었는지 까먹고 있었다.. 추가로 자바에서는

       클래스에 final 키워드는 잘쓰지 않는데 (내가 봤던 코드만 그럴수도..) 코틀린에서는 클래스 뿐만아니라 이것저것 final 이 기본 키워드이다.

       요거를 보면서 코틀린이 final을 상당히 좋아하는구나라는 철학(?)을 느낄 수 있었다.

 

b.  자바 스타일로 클래스 만들어보기

open class Hotel(
    name: String?, address: String?
) {

    val name: String? = name
        private set
        open get
    val address: String? = address
        private set
        open get

}

  -  다소 억지(?)로 코틀린 클래스를 자바 스타일로 만들보았다. 이를 디컴파일 해보면 

  -  자주 보던 형태의 자바 클래스 스타일로 만들었는데 차이는 @Nullable이 붙어있는 것을 볼 수 있다. 코틀린는 아주 빡빡하게 null을 처리하고 있다.

 

 c.  코틀린 스타일로 클래스 만들어보기

class Hotel(val name: String, val address: String)

  -  코틀린은 이렇게 코드 한줄로 필드, 생성자, getter 까지 표현하면서 final, null 처리까지 해주는 것을 볼 수 있다. 

  -  번외로 생성자의 매개변수를 여러가지 테스트 해보자

class Hotel(val name: String, var address: String)

 - var 키워드로 변경했더니 final이 사라지고 getter, setter 가 생기는 것을 볼수 있다.

class Hotel(val name: String, address: String)

  -  var, val 키워드를 붙이지 않은 경우에는 생성자의 매개변수로만 추가된다.

 

나.  Hotel 클래스

 a.  가격 추가하기

  -  Hotel 클래스에 가격(price) 프로퍼티를 추가해보자. 가격(price) 자체가 변경된다고 한다면..

class Hotel(val name: String, val address: String, var price: Int)

 -   단순하게 가격은 변경되는거니까.. var 키워드로 price 프로퍼티를 생성했다.

fun main(args: Array<String>) {

    val seeHotel = Hotel(name = "속초바다호텔", address = "강원도 속초시 동해대로", price = 89000)
    println(seeHotel.price)

    seeHotel.price = 90000
    println(seeHotel.price)
}

 

 b.  코틀린 setter 제거하기

  -  요즘은 setter를 아마 싫어하는 사람들이 많을 것 같다. 보기싫으니(?) getter 만 남기고 빼보자

   => 어떤 값이 있든, 어떤 상황이든 지금 변경하는 값으로 바꾼다 라는 의미가 있으니 너무 싫어하진 말자!

class Hotel(val name: String, val address: String, price: Int) {

    var price = price
        private set

}

  -  디컴파일에서 알 수 있듯이 생성자에 매개변수를 두고 내부에 프로퍼티를 추가해서 private set 키워드로 setter를 제거할 수 있다.

 

 c.  private val

  -  생각해보면 호텔 가격은 여러 사이트를 보면 항상 다르지만 오프라인에서 호텔 문을 활짝 열고 들어가면 동일한 비싼 가격을 받는 경우가 있다. 

  -  결국 이 비싼 가격이 기준 가격이고 이것저것 이름을 붙여서 할인가를 주는 것 뿐이지 가격은 변경되지 않는다.  이걸로 다시 코드를 바꿔보면

class Hotel(val name: String, val address: String, private val price: Int) {

    fun getNormalPrice() = price
    fun getSummerPrice() = (price * 0.8).roundToInt()
    fun getWinterPrice() = (price * 0.5).roundToInt()
}

  -  가격을 변경할수 없도록 private val로 설정해서 getter, setter 만들지 않았고 각각의 가격들은 메서드로 만들었다.

fun main(args: Array<String>) {

    val seeHotel = Hotel(name = "속초바다호텔", address = "강원도 속초시 동해대로", price = 89000)

    println(seeHotel.getNormalPrice())
    println(seeHotel.getSummerPrice())
    println(seeHotel.getWinterPrice())
}

  -  뭔가 괜찮은 것 같다. 하지만 만약 이 상태로 코드리뷰를 받는다면 아마 리뷰에 어디서 자바 냄새(?) 안나요?  라는 코멘트를 받을지도 모른다..

 

 d.  get()

fun main(args: Array<String>) {

    val seeHotel = Hotel(name = "속초바다호텔", address = "강원도 속초시 동해대로", price = 89000)

    println(seeHotel.normalPrice)
    println(seeHotel.summerPrice)
    println(seeHotel.winterPrice)
}

  -  아까와는 반대로 결과를 먼저 만들어보자 위의 코드처럼 코틀린이라면 저렇게 불필요한 get 명칭을 다때버리고 싶을수 있다. 바꿔보자

class Hotel(val name: String, val address: String, private val price: Int) {
    
    val normalPrice
        get() = price
    val summerPrice
        get() = (price * 0.8).roundToInt()
    val winterPrice
        get() = (price * 0.5).roundToInt()
}

 -  이렇게 get() 이라는 키워드를 통해 마치 객체 내에 프로퍼티를 가져오듯 커스텀 메서드도 동일하게 만들어서 깔끔하게 코드를 작성할 수 있다.!

 

다.  data class 

 a. Dto 만들기

  -  위에 Hotel 클래스에 이어서 클라이언트로 부터 Hotel을 등록해야하는 경우 DTO 클래스가 필요할 수도 있다.

  -  보통 자바에서는 final 형태로 필드들을 정의해서 getter만 만들고 하는데 코틀린에서는 간단하게 data class 키워드로 간단하게 만들수 있다.

data class HotelRequestDto (
    val name: String,
    val address: String,
    val price: Int
)

 

 b.  자동생성되는 메서드 

  -  toString(), equals, hashcode, copy, componentN

  -  위의 그림에서 볼 수 있듯이 copy의 경우 새로운 객체를 만드는 deep copy 하는 것을 볼 수 있다.

 

 c.  ComponentN

  -  이 메서드는 자바에서는 없는 부분이데 코틀린에서 제공하는 객체 분해를 위한 메서드 이다.     

     => 자바스크립트에서 자주 보던 기능과 비슷하다.

val hotelRequestDto = HotelRequestDto(name = "올림픽호텔", address = "올림픽대로", price = 1000)
val (name, address, price) = hotelRequestDto
val (one, two, three) = hotelRequestDto

  -  주의할점은 메서드 명에서도 알 수 있듯이 필드명이 아닌 순서로 분해하기 때문에 중간에 값이 추가된다거나 하면 큰 문제가 발생할 수 있다.

 

 

반응형

블로그의 정보

57개월 BackEnd

BFine

활동하기