본문 바로가기

Programming Language/Kotlin

Kotlin in Action - 2

코틀린 기초

코틀린은 타입 선언 생략이 가능하다.

코틀린은 변경 가능한 데이터 보다 불변 데이터 사용을 권장한다.

함수와 변수

Hello, world

fun main (args: Array<String>) {
	println("Hello, world!")
}
  • fun 키워드로 함수 선언
  • 파라미터 이름 뒤에 타입 선언
  • 함수를 최상위수준에 정의 가능. 클래스 불필요
  • System.out.println 대신에 println
  • 세미콜론 불필요

함수

함수 선언은 fun 키워드로 시작한다. fun 다음에는 함수 이름이 온다.

함수 이름 뒤에는 괄호 안에 파라미터 목록이 온다.

위 그림은 코틀린 함수의 기본 구조를 보여준다. 코틀린 if 는 문장(statement)이 아니고 결과를 만드는 식(expression)이다.

문(statement)과 식(expression)의 구분

코틀린에서 if 는 식이지 문이 아니다.
식은 값을 만들고, 다른 식의 하위요소로 계산에 참여 할 수 있다.
반면 문은 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며, 아무런 값을 만들어 내지 않는다.

자바에서는 모든 제어구조가 문인 반면, 코틀린에서는 루프를 제외한 대부분 제어 구조가 식이다.

식이 본문인 함수

위 그림의 함수를 더 간결하게 표현 가능하다. 중괄호, return, 반환 타입을 없앨 수 있다.

fun max (a: Int, b: Int) = if (a > b) a else b

코틀린은 정적 타입 지정 언어 이므로, 컴파일 시점에 모든 식의 타입을 지정해야 한다. 하지만 식이 본문인 함수의 경우 굳이 사용자가 반환 타입을 지정하지 않아도 컴파일러가 식의 결과타입을 반환 타입으로 정해준다.

식이 본문인 함수의 반환 타입만 생략 가능하다. 블록이 본문인 함수는 반환타입을 지정하고, return 문을 사용해서 반환값을 명시해야한다.

변수

자바는 변수 선언시 타입이 맨 앞에 온다.

코틀린은 타입 지정을 생략하는 경우가 흔하다.

초기화 식이 없다면 타입을 반드시 지정해야 한다.

val quetion = "질문"
val answer = 42
---
val answer: Int = 42

변경 가능한 변수, 불가능한 변수

변수 선언 키워드는 두가지가 있다.

  • val(value)
    • 변경 불가능한(immutable) 참조를 저장하는 변수다.
    • val로 선언된 변수는 일단 초기화 한 후 재대입이 불가능하다.
    • 자바의 final 변수
  • var(variable)
    • 변경 가능한(mutable) 참조다.
    • 이 변수의 값은 바뀔 수 있다.
    • 자바의 일반 변수

기본적으로 모든 변수를 val 키워드로 선언하고, 나중에 필요시 var 로 변경하라.

val 변수는 블록을 실행할 때 한번만 초기화 해야 한다.

하지만 조건에 따라 여러 값으로 초기화 할 수 도 있다.

val message: String
if (canPerformOperation()) {
	message = "Success"
	// 연 산 을 수 행 한 다 .
} else {
	message = "Failed"
}

val 참조 자체는 불변일지라도 그 참조가 가리키는 객체 내부 값은 변경 가능하다.

val languages = arrayListOf("Java") <---- 볼변 참조를 선언한다.
languages.add("Kotlin") <---- 참조가 가리키는 객체 내부를 변경한다.

var 키워드는 변수 값은 변경 가능 하지만 타입은 바뀌지 않는다.

var answer = 42
answer = "no answer"  //  컴파일오류발생 "Error:type mismatch"

클래스와 프로퍼티

자바 클래스 Person

/* 자바 */
public class Person {
	private final String name;

	public Person(String name){
		this.name = name;
	}

	public String getName() {
		return name;
	}
}

자바는 생성자 본문에 같은 코드가 반복적으로 들어가는 경우가 많다.

코틀린은 그런 필드 대입을 더 적은 코드로 작성 가능하다.

코틀린 클래스 Person

class Person(val name: String)

이런 코드없이 데이터만 저장하는 클래스를 값 객체라고 부른다.

코틀린의 기본 가시성은 public이므로 이런 경우 변경자를 생략해도 된다.

프로퍼티

클래스 개념의 목적은 데이터를 캡슐화 하고, 캡슐화한 데이터를 다루는 코드를 한 주체 아래 가두는 것이다.

자바는 데이터를 필드에 저장하고, 멤버 필드의 가시성은 보통 비공개(private)이다.

자바에서 필드와 접근자를 한데 묶어 프로퍼티(property)라고 부른다.

코틀린은 프로퍼티를 언어 기본 기능으로 제공하며, 자바 필드와 접근자 메소드를 대신한다.

class Person(
	val name: String,
	// 읽기전용 프로퍼티, (비공개)필드와 (공개) 게터를 만들어 낸다.
	var isMarried: Boolean
	// 쓸 수 있는 프로퍼티, (비공개)필드, (공개)게터, (공개)세터를 만든다.
)

자바의 Person 클래스를 사용하는 법

Person person = new Person("Wangmin", true);
System.out.println(person.getName());
System.out.println(person.isMarried());

코틀린의 Person 클래스를 사용하는 법

val person = Person("Wangmin", true)
println(person.name)
println(person.ismarried)

person.isMarried = false

게터를 호출하는 대신 프로퍼티를 직접 사용한다.

코틀린이 자동으로 게터를 호출해준다.

세터 대신 프로퍼티를 변경하면 세터를 호출한다.

커스텀 접근자

class Rectangle (val height: Int, val width: Int) {
	val isSquare: Boolean
		get() {  // 프로퍼티 게터 선언
			return height == width
		}
}

isSqaure 프로퍼티에는 자체 값을 저장하는 필드가 필요 없다.

프로퍼티에 접근할 때마다 게터가 프로퍼티 값을 매번 다시 계산한다.

선택 표현과 처리 : enum과 when

when은 자바의 switch를 대치하되 더 강력하다.

enum을 선언하는 방식과 스마트 캐스트에 대해서도 함께 살펴본다.

enum 클래스 정의

enum class Color {
 RED, ORANGE, YELLOW
}

자바와 마찬가지로 enum은 단순히 값만 열거하는 존재가 아니다.

enum클래스 안에도 프로퍼티나 메소드를 정의 할 수 있다.

enum class Color (
 val r: Int, val g: Int, val b: Int
) {
	RED(255,255,0),
	ORANGE(255,165,255);

	fun rgb() = (r*256+g) * 256 + b
}

enum에서도 일반적인 클래스와 마찬가지로 생성자와 프로퍼티를 선언한다.

when 으로 enum 클래스 다루기

if와 마찬가지로 whene도 값을 만들어내는 식이다.

본문인 함수에 when을 바로 사용 할 수 있다.

fun getMnmonic(color: Color) = 
	when (color) {
		Color.RED -> "빨"
		Color.ORANGE -> "주"
		Color.YELLOW -> "노"
		Color.GREEN, Color.BLUE, Color.INDIGO -> "나머지"
	}

자바와 달리 분기 끝에 break를 넣지 않아도 된다.

한 분기 안에서 여러 값을 매치 패턴으로 사용 할 수도 있다.

when과 임의의 객체를 함께 사용

분기 조건에 상수만 가능한 자바 switch 와 달리 코틀린의 when의 분기 조건은 임의의 객체를 허용한다.

두 색을 혼합했을 때 미리 정해진 결과를 알려주는 함수

fun mix(c1: Color, c2: Color) = 
	when (setOf(c1, c2)) {
		setOf(RED,YELLOW) -> ORANGE
		setOf(YELLOW, BLUE) -> GREEN
		else -> throw Exception("dirty color")
	}

setOf 함수는 여러 객체를 퐇마하는 집합인 set으로 만드는 함수.

각 원소의 순서는 상관없다.

when의 분기 조건 부분에 식을 넣을 수 있기 때문에 많은 경우 코드를 더 간결하게 작성 가능하다.

인자 없는 when 사용

각 분기 조건이 Boolean이면 when에 인자를 없이 사용 할 수 있다.

when{
	(a == b && c == a) -> 1
	(a != b || c != a) -> 2
}

이터레이션: while, for

while

코틀린의 while과 do-while은 자바와 다르지 않다.

while(조건){
// ...
}

do {
// ...
} while ()

범위와 수열

코틀린엔 자바의 for 루프(변수 초기화, 루프시마다 변수 갱신, 루프 조건 거짓시 종료)에 해당하는 요소가 없다.

코틀린은 범위(range)를 사용한다.

val oneToTen = 1..10

범위는 양 끝을 포함하는 구간이다.(1, 10 포함)

이렇게 어떤 범위에 속한 값을 일정한 순서로 이터레이션 하는 경우를 수열(progression)이라 한다.

범위 표현

val tenToOne = 10 downTo 1 // 역방향 범위 : 10, 9, 8, ... 1
val oneToTenStepTwo = 1..10 step 2 // 증가값 변화 : 1 -> 2 (1,3,5,7,9)

val tenToOneStepTwo = 10 downTo 1 step 2 // 역방향, 증가값 변화 (10, 8, 6, 4, 2)

val oneToNine = 1 until 10 // 1..10-1 과 동일 

Map에 대한 이터레이션

val binaryReps = TreeMap<Char, String>()

for (c in 'A'..'F') { // A부터 F까지 문자 범위를 순회한다.
	val binary = Integer.toBinaryString(c.toInt())
	binaryReps[c] = binary
}

for((letter, binary) in binaryReps) { // 맵의 키와 값을 두 변수에 대입하여 순회한다.
	println("$letter = $binary")
}

컬렉션 이터레이션

val list = arrayListOf(1,2,3)
for((index, element) in list.withIndex()) { // 인덱스와 함께 컬렉션 순회
	println("$index: $element")
}

in으로 컬렉션이나 범위 원소 검사

in 연산자를 통해서 어떤 값이 범위에 속하는지 검사 할 수 있다. 반대로 !in을 사용하면 속하지 않는지 검사가 가능하다.

'q' in 'a'..'z' -> true
'x' !in '0'..'9' -> true

코틀린의 예외 처리

코틀린의 예외처리는 자바나 다른 언어와 비슷하다.

코틀린은 체크예외와 언체크예외를 구분하지 않는다.

if(percentage !in 0..100){
	throw IllegalArgumentException(
	"A percentage value must be between 0 and 100: $percentage")
}

다른 클래스와 마찬가지로 new 키워드는 사용할 필요 없다.

자바와 달리 코틀린의 throw는 식이므로 다른 식에 포함될 수 있다.

if (number in 0..100)
	number
else
	throw IllegalArgumentException(
	"throw"는 식이다. "A percentage value must be between 0 and 100: $number")

try를 식으로 사용

val number = try{
	Integer.parseInt(reader.readLin())
} catch( e: NumberFormatException){
	return
}

요약

  • 함수를 정의할 때 fun 키워드 사용
  • val, var은 각각 읽기 전용 변수와 변경 가능한 변수
  • 문자열 템플릿 “$variable”
  • 값 객체 클래스 간결히 표현 가능
  • if는 식이며, 값을 만들어 낸다
  • when은 switch와 비슷하지만 강력하다
  • for, while, do-while 루프는 자바와 비슷하다.
    • 코틀린의 for는 자바보다 편리하다.
  • 1..5와 같이 범위를 만들어 낸다.
  • in, !in을 사용해서 범위 안에 값을 검사한다.
  • 예외처리는 자바와 비슷하다. 함수가 던질 수 있는 예외를 선언하지 않아도 된다.

참조

 

Kotlin in Action - YES24

코틀린이 안드로이드 공식 언어가 되면서 관심이 커졌다. 이 책은 코틀린 언어를 개발한 젯브레인의 코틀린 컴파일러 개발자들이 직접 쓴 일종의 공식 서적이라 할 수 있다. 코틀린 언어의 가장

www.yes24.com

 

'Programming Language > Kotlin' 카테고리의 다른 글

Kotlin in Action - 1  (0) 2021.12.19