kotlin 공부

정명진·2023년 5월 27일
0

2023/05/27

코틀린은 컬렉션 생성에 여러 방법이 있다.

그중 listOf, mutableListOf에 대해 알아보자.

@Test
fun listOfTest() {
     var nums = listOf(1, 2, 3, 4, 5)
     var sets = setOf(1, 1, 1, 1,1 )
     Assertions.assertEquals(sets.size, 1)
}

listOf은 전달 받은 파라미터의 타입을 추론해 list로 반환해주는 함수다.

하지만 이렇게 생성된 list는 read only만 가능한 상태다.

실제로 add 메소드가 없다.

@Test
fun mutableListOfTest() {
    var nums = mutableListOf(1, 2, 3, 4, 5)
    var sets = mutableSetOf(1, 1, 1, 1,1 )
    sets.add(2)
    Assertions.assertEquals(sets.size, 2)
}

이렇게 mutableListOf으로도 설정이 가능하다.

이렇게 선언하면 add가 가능해진다.

2023/05/29

let + elvis operation

kotlin에서 let과 elvis op을 같이 사용하면 null safe 하게 엔터티를 도메인으로 변경할 수 있다. 기타 다른 곳에서도 사용이 가능하다. 나같은 경우 헥사고널 아키텍처를 사용하면서 어댑터에서 엔터티를 도메인으로 변환하는 작업이 필요했다. Java의 경우 Optional을 사용해서 해결했는데 kotlin에선 다음과 같이 해결 가능했다.

override fun findByEmail(email: String): User = springDataUserRepository.findByEmail(email)?.let { userMapper.mapToDomainEntity(it) }?: throw ApiException(404, "Email not existed...")

?과 let을 이용해 null safe하게 호출후 마지막으로 elvis op을 상요해 null을 처리해주었다.
꽤나 유용한 방법이며 kotlin cookbook에서도 챕터가 있을 정도다. 잘 숙지해둬서 사용해야겠다.

let을 체이닝 역할로 쓰는법

@Test
    fun letChainTest() {
        val nums = mutableListOf(1, 3, 5, 6,11, 22, 33, 100)
        nums.filter { it % 2 == 1 }.let(::println)

        Gson().fromJson(URL("http://api.open-notify.org/astros.json").readText(), AstroResult::class.java).people.map { it.name }.let(::println)
    }
    
# result
[1, 3, 5, 11, 33]
[Sergey Prokopyev, Dmitry Petelin, Frank Rubio, Fei Junlong, Deng Qingming, Zhang Lu, Stephen Bowen, Warren Hoburg, Sultan Alneyadi, Andrey Fedyaev]

let을 사용하지 않았다면 결과를 assign 해서 출력해야 하지만 let을 사용하면서 변수에 할당하지 않고 바로 출력이 가능하다.

컴포지트 구성시 by 사용하기

camera와 phone 기능이 있는 SmartPhone 클래스가 있다고 가정하자. 이를 컴포지트로 갖게 될때 by 키워드를 사용하면 보일러 플레이트 코드를 줄이면서 개발을 할 수 있다.

예를 들어 다음과 같이 구성이 되어 있다고 하자.

interface Snappable {
    fun takePicture(): String
}

class Camera: Snappable {
    override fun takePicture() = "Taking pictures ..."
}

interface Dialable  {
    fun dial(number: String): String
}

class Phone : Dialable {
    override fun dial(number: String) = "Dialing $number..."
}

class SmartPhone(
    private val phone: Dialable = Phone(),
    private val camera: Snappable = Camera()
)

만약 다음과 같이 구성되어 있다면 SmartPhone 클래스에서 wrapper 메소드를 작성해주지 않아 phone의 dial, camera의 takePicture 메소드를 사용할 수 없다. 하지만 다음과 같이 변경해주면 자동으로 코틀린에서 생성해줘서 해당 메소드들을 사용할 수 있다.

class SmartPhone(
    private val phone: Dialable = Phone(),
    private val camera: Snappable = Camera()
) : Dialable by phone, Snappable by camera

by를 적절하게 사용하면 유용할 것 같다.

profile
개발자로 입사했지만 정체성을 잃어가는중... 다시 준비 시작이다..

0개의 댓글