Hello()()()()() 이건 뭐지..?

Jaychy·2021년 6월 24일
1

알아가는 것

목록 보기
9/11
post-thumbnail

Github 코틀린으로 개발하면서 궁금했던 점에 대해 고찰하는 곳.

개요

이번 글은 "이런 식으로 만들 수도 있구나..!" 라는 정도로만 읽어주시면 감사하겠습니다.

코틀린에는 invoke 관례라는 것이 있습니다.
함수의 이름을 invoke로 짓고 operator 키워드를 통해 연산자 오버로딩을 하게 되면,
관례에 따라 그에 맞는 기능을 하도록 정의됩니다.

특히 invoke 관례는 잘못 사용하면 알 수 없는 코드를 만들 수 있습니다.

연산자 오버로딩? 자바에는 없는데

자바에서는 연산자 오버로딩 기능을 지원하지 않습니다.
하지만 코틀린에서는 개발상 편의를 위해서 관례를 이용하여 이를 구현합니다.

코틀린에는 plus, minus, get, getValue, invoke
수많은 연산자 오버로딩용 관례가 있습니다.
이 중 가장 괴랄한? invoke 연산자에 대해서 알아보도록 하겠습니다.

invoke 사용해보기

invoke 메소드의 관례는
이 메소드를 호출할 때는 메소드의 이름을 명시하지 않아도 된다는 것입니다.

class AnyClass {
    operator fun invoke() = println("any class")
}

이렇게 invoke 연산자를 정의하게 되면 다음과 같이 사용할 수 있습니다.

val anyClass = AnyClass()
anyClass()

anyClass()는 사실 anyClass.invoke()로 컴파일 됩니다.

그럼 Hello()()()()()는?

이는 this를 리턴하는 방식을 통해 속임수를 사용한 것입니다.
실제 Hello 클래스는 다음과 같습니다.

class Hello {
    operator fun invoke(): Hello {
        println("hello")
        return this
    }
}

따라서 Hello()()()()()는 괄호의 갯수 - 1만큼 hello를 출력하게 됩니다.
또한 실제로 Hello()()()()()는 다음과 같이 컴파일 됩니다.

Hello().invoke().invoke().invoke().invoke()

결론

Hello()()()()()invoke 관례를 이용한 꼼수입니다.

profile
아름다운 코드를 꿈꾸는 백엔드 주니어 개발자입니다.

0개의 댓글