본문 바로가기

개발/Language

Kotlin - internal 접근제어자

회사에서 코틀린 스터디를 시작했다!

 

클린 코드 스터디 이후 두 번째 스터디다.

 

개인적으로 코틀린을 써보려고 해봤지만

최근에는 손을 놓고 있어서 다시 보니까 감회가 새로웠다.

 

이번 스터디를 통해서 코틀린을 더 잘 쓸 수 있도록

많이 배우는 시간이 되었으면 좋겠다!_!

 

internal은 처음 코틀린을 쓸 때는,,

이게 뭥미??

 

어떤 경우에 쓰는 녀석인고...

잘 와닿지 않았다.

 

그런데 이번에 스터디 때문에 공부하다가

문득 한번 써봐야겠다+_+ 싶어서 사용해보고

그 내용을 정리해보게 되었다.


internal visibility modifier

 

Kotlin과 Java의 접근 제어자는 거의 유사(?)하다.

 

public, protected, private...

 

public과 private은 똑같다!

 

protected는 Kotlin에서는 상속 관계에서만 접근이 가능하다.

동일한 패키지에 위치한 관계이더라도 상속하지 않았다면 접근이 불가능하다.

 

 

그럼 Java의 package-private은 어디갔느냐?

 

 

Kotlin에서는 없애버리고 internal이라는 새로운 접근 제어자를 만들었다.

 

internal은 동일한 모듈 안에서만 접근이 가능하다.

 

코틀린 문서에 따르면 모듈이라는 단위는 다음과 같다.

- An IntelliJ IDEA module.
- A Maven project.
- A Gradle source set (with the exception that the test source set can access the internal declarations of main).
- A set of files compiled with one invocation of the <kotlinc> Ant task.

 

그런데 이렇게 글로 읽어서는 와닿지가 않는다.

 

그래서 IntelliJ IDEA module 두 개를 만들어서 직접 사용해보았다.

 


IntellJ IDEA module로 internal 써보기

 

 

internal class를 선언한 모듈을 callee라고 만들고,

internal class를 사용하는 모듈을 caller라고 만들었다.

 

 

callee 모듈에는 Internal이라는 코틀린 클래스를 만들었다.

 

internal class Internal {
    val publicField = "public field"
    internal val internalField = "internal field"

    fun publicMethod() {
        println("public method")
    }

    internal fun internalMethod() {
        println("internal method")
    }
}

 

 

caller 모듈에서 코틀린 코드로 callee의 Internal 클래스에 접근하면 어떻게 될까??

 

 

Internal instance 만드는 코드를 빌드하려 하면 컴파일 에러가 난다.

 

코틀린 컴파일러가 다른 모듈의 internal 접근제어자가 붙은 아이를

사용할 수 없다는 걸 잘 알고 있기 때문이다. 

 

 

그럼 자바 코드로 Internal 클래스에 접근하면?

 

 

IDE에서 에러를 준다..

하지만 무시하고 빌드를 해본다.

 

 

빌드도 잘되고... 실행도 된다!!!?

 

자바에서는 internal 접근제어자가 없다.

따라서 internal 접근제어자는 자바 바이트코드로 변환될때 자바의 public으로 바뀌게 된다.

 

그래서 자바 컴파일러 입장에서는 Internal은 접근할 수 있는 클래스인 것이다.

 

 

그리고 Internal의 public field나 public method를 불러보자.

 

 

잘 불린다 ㅎㅎ

 

 

그럼 internal field와 internal method는 어떨까?

 

 

음?? 뭔가 바뀌어있다..

 

internalMethod$callee()든 getInernalField$callee()든 부르더라도

빌드는 잘 된다.

 

 

다만 코틀린 컴파일러에서 노-력을 하고 있다는걸 알 수 있는데...

 

internal 제어가 붙은 클래스 프로퍼티에는 ${MODULE_NAME}을 붙여 mangling을 하고 있다.

 

타 모듈 개발자에게 이건 internal인뎁?? 정말 쓸껴?!

라고 말하며 네이밍도 부르면 큰일날 것처럼 안예쁘게 만들었다.

 

덕분에 아.. 쓰기 싫다.. 라는 생각이 들지 않을까 싶다.

 


 

결론은,,

 

 

자바로 안드로이드 라이브러리 개발을 하면서

클라이언트에게 공개하고 싶지 않은 코드들은

package-private이나 proguard 설정을 통해 감추는 작업을 해왔다.

 

하지만 internal 접근제어자를 사용하면 모듈 캡슐화를 더 쉽게 실현할 수 있을 것 같다!!

 

'개발 > Language' 카테고리의 다른 글

Java - checked/unchecked exception  (0) 2021.01.13
Kotlin - 인터페이스 default 메서드  (0) 2020.12.19