본문 바로가기
  • 개발하는 곰돌이
Programming Language/Kotlin & Java

Kotlin에서 한 줄로 받은 입력을 여러개의 변수에 할당하는 방법(구조 분해)

by 개발하는 곰돌이 2022. 12. 8.

Java에서는 한 줄로 받은 입력을 여러개의 변수에 할당하려면 Scanner 클래스의 next()로 변수마다 하나씩 할당해주거나 BufferedReader 클래스의 readLine()으로 한 줄을 입력받은 후 split()이나 StringTokenizer로 입력을 분할하여 하나씩 할당해줘야 했다. 하지만 Kotlin에서는 똑같이 한 줄로 입력을 받았을 때, 최대 5개까지의 변수를 한 줄의 코드로 할당할 수 있다. 

Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
int d = sc.nextInt();
int e = sc.nextInt();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
int e = Integer.parseInt(st.nextToken());

위와 같이 Java의 경우에는 변수의 개수만큼 코드의 길이가 길어지고, 할당하려는 n개의 변수가 같은 타입이더라도 각각 형변환을 해줘야하는 번거로움이 있었다. 하지만 Kotlin에서는 이러한 일련의 과정을 아래와 같은 한 줄로 처리할 수 있다.

var (a, b, c, d, e) = readln().split(' ').map { it.toInt() }

이 한줄로 작성된 Kotlin 코드는 위의 Java 코드들과 마찬가지로 한 줄에 띄어쓰기로 구분된 5개의 수를 입력받았을 때 a, b, c, d, e에 하나씩 할당하는 동작을 수행한다.(내부적으로 동작 과정은 다르다.) 이러한 방법으로 변수를 할당하는 것을 구조 분해라고 한다. 또한, 5개의 변수가 모두 동일한 타입이라면 map 함수를 통해 한번에 형 변환을 할 수 있다. 이 map 함수의 내부 구조를 보면 다음과 같다.

함수의 구조를 보면 원본 T 타입을 담는 Iterable 객체의 확장 함수로 작성되어 있는데, 원본 T 타입에 transform() 함수를 적용하여 변환한 R 타입을 담는 List를 반환한다. 그리고 이 List 클래스에 componentN()라는 특이한 연산자 함수가 있다.

componentN() 함수가 1부터 5까지만 있기 때문에 한번에 최대 5개의 변수에 값을 할당할 수 있고, 6개째부터는 component6() 함수가 없다는 컴파일 에러가 발생한다.

 

그밖에도 이 componentN() 함수는 List의 확장함수이기 때문에 위와 같은 입력뿐만 아니라 별도의 리스트에서도 아래와 같이 0~4번째 인덱스의 값을 최대 5개의 변수에 한 번에 할당할 수 있다.

var (a, b, c, d, e) = listOf(18, 42, 31, 74, 95)

이러한 구조 분해는 componentN() 메소드만 작성되어 있다면 어느 타입이라도 적용할 수 있다. 가령 Person 클래스가 있을 경우엔 아래와 같은 방법으로 변수를 할당할 수도 있는데, 이는 Data Class에서 자동으로 componentN() 메소드를 제공하기 때문이다. 이 경우에는 클래스의 생성자에 작성된 필드 순서대로 변수에 할당된다.

fun main() {
    val person = Person("AAA", 50)
    val (a, b) = person
    println(a)
    println(b)
}

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

/*
AAA
50
*/

댓글