코틀린 기본기 - 변수, Type, 연산자

Janek·2023년 2월 11일
0

코틀린 기본기

목록 보기
1/3
post-thumbnail

해당 포스팅은 인프런에서 제공하는 최태현 님의 '자바 개발자를 위한 코틀린 입문'을 수강한 후 정리한 글입니다. 유료 강의를 정리한 내용이기에 제공되는 예제나 몇몇 내용들은 제외하였고, 정리한 내용을 바탕으로 글 작성자인 저의 언어로 다시 작성한 글이기에 서술이 부족하거나 잘못된 내용이 있을 수 있습니다. 그렇기에 해당 글은 개념에 대한 참고 정도만 해주시고, 강의를 통해 학습하시기를 추천합니다.

변수 선언

코틀린은 모든 변수에 수정 가능 여부를 명시해주어야 한다. val 키워드는 불변이나, 컬렉션에는 element를 추가할 수 있다.

var num1 = 10L	// var : 가변 
val num2 = 10L	// val : 불변

또한 타입을 명시적으로 선언하지 않아도 타입을 추론하며, 명시적으로 선언해줄 수도 있다.

var num1: Long = 10L
val num2: Long = 10L

모든 변수는 우선 불변인 val로 선언하고 필요할 경우에만 var로 변경하는 것이 좋다.

코틀린에서 변수는 기본적으로 null이 허용되지 않으며 nullable 변수를 생성하기 위해서는 타입?과 같이 명시적으로 선언해줘야 한다.

var num: Long?

또한 객체를 인스턴스화 할 때 new를 붙이지 않는다.

val obj = Object("New Object");

코틀린에서는 기본 자료형과 참조 자료형의 구분이 감춰져있다. 일반적으로는 자료형의 구별 없이 사용할 수 있으며, null이 허용된다면 참조형, 아니라면 기본형으로 선언된다. 즉 boxing/unboxing을 고려하지 않아도 되도록 코틀린이 처리 해준다.

null 안정성

코틀린은 null이 가능한 타입을 완전히 다르게 취급하며, 한 번 null check를 하면 컴파일러가 non-null임을 알 수 없다.(특히 Java의 코드를 사용하는 플랫폼 타입일 경우) 따라서 이를 위한 기능을 제공한다.

안전한 호출(safe call)

안전한 호출은 체인(chain)할 때 ?.를 사용하여 null이 아니면 해당 체인의 연산을 실행하고, null이면 실행하지 않는다. nullable 타입일 경우 안전한 호출을 통해서만 실행이 가능하다.

val str: String? = "ABC"
str.length // str이 nullable이기 때문에 실행 불가능
str?.length

Elvis 연산자

엘비스 연산자는 ?:를 사용하여 앞의 연산 결과가 null이면 뒤의 내용을 호출해준다.

str?.length ?: 0 // str.length의 값이 null일 경우 0 실행

엘비스 연산은 early return에도 사용할 수 있다.

fun calculate(number: Long?): Long {
	number ?: return 0
    ... null이 아닐 경우 로직
}

null 아님 단언

nullable 타입이지만 null이 될 수 없는 경우 !!를 사용할 수 있다.

fun startsWithA(str: String?): Boolean {
	return str!!.startsWith("A")
}

Type

코틀린은 선언된 기본값을 보고 타입을 추론하지만 타입간의 변환은 언제나 명시적으로 이루어져야 한다.

val num1 = 4
val num2: Long = num1 // Type mismatch
val num2: Long = num1.toLong()	// 명시적 형변환 필요

Java에서의 instanceof에 해당하는 키워드로 is 키워드가 있으며, 일반 타입은as를 통해 형변환이 가능하다.(기본 타입도 가능)

fun printAgeIfPerson(obj: Any) {
    if (obj is Person) {    
    // is == java: instance of
	// val person = obj as Person  
    // as = java: (Object) obj, 생략 가능
        println(obj.age)
    }
}

또한 nullable 변수에 대해 적절한 처리가 필요하다.

val num1: Int? = 3
val num2: Long = num1?.toLong() ?: 0L

fun printAgeIfPersonNullable(obj: Any?) {
    val person: Person? = obj as? Person    
    // as? : obj가 해당 타입이면 형변환, null이거나 해당 타입이 아니면 null을 반환
    println(person?.age)
}

Any

Java의 Object 처럼 모든 객체의 최상위 타입으로, 모든 기본 자료형의 최상위 타입 또한 Any이다. Any 자체로는 null을 포함할 수 없으며, Any?를 통해 포함시킬 수 있다. 기본적으로 equals, hashCode, toString이 존재한다.

Unit

Java의 void와 동일한 역할이지만, void와는 다르게 Unit 그 자체를 타입 인자로 사용 가능하다.

Nothing

함수가 정상적으로 끝나지 않았다는 사실을 표현하는 역할로, 무조건 예외를 반환하거나 무한 루프 함수 등에 사용된다.

fun fail(message: String): Nothin {
	throw IllegalArgumentException(message)
}

String interpolation

코틀린은 문자열의 동적인 가공을 위해 아래와 같이 String interpolation을 지원한다.

val person = Person("test", 100)
println("이름: ${person.name} / 나이: ${person.age}")

${변수}를 사용하면 해당 변수의 값이 포함되며 $변수를 사용할 경우 해당 변수명이 포함된다.

또한 """문자열""".trimIndent()을 통해 편리하게 여러 줄의 문자열을 가공할 수 있게 해준다.

String indexing

문자열에서 문자를 가져올 때 [index]를 통해 Java의 배열과 같이 가져올 수 있다.

연산자

단항 연산자 / 산술 연산자

단항/산술 연산자는 Java와 동일하다. ++, --로 단항 연산을 할 수 있으며 +, -, *, /, %로 산술 연산을, +=, -=, *=, /=, %/로 산술 대입 연산이 가능하다.

비교 연산자

비교 연산자 또한 Java와 동일하게 >, <, >=, <=, == 으로 할 수 있다. 단, Java와 다르게 객체를 비교할 때 비교 연산자를 사용하면 자동으로 compareTo를 호출해준다.

두 객체의 값이 같은지 비교하는 동등성 비교에 equals, 주소가 같은 완전히 동일한 객체인지 비교하는 동일성 비교에 ==를 사용하는 Java와는 다르게 동등성에 ==를 사용하여 간접적으로 equals를 호출하며, 동일성 비교는 ===을 사용한다.

논리 연산자

&&, ||, !을 통해 논리 연산이 가능하며, Java와 같이 Lazy 연산을 수행한다.

이 외에 코틀린에만 존재하는 연산자로는 컬렉션의 범위에 포함되어있는지의 여부를 리턴하는 in/!in, a에서 b까지의 범위 객체를 생성하는 a..b, a[i], a[i] = b로 a에서 특정 index i를 통해 값을 처리할 수 있는 연산자가 존재한다.

연산자 오버로딩

코틀린에서는 아래와 같이 객체마다 연산자를 직접 정의할 수 있다.

data class Money(
    val amount: Long
) {

    operator fun plus(other: Money): Money {
        return Money(this.amount + other.amount)
    }

}
...
val money1 = Money(1_000L)
val money2 = Money(2_000L)
print(money1 + money2) // Money(3_000L)
profile
만들고 나누며, 세상을 이롭게 하고 싶습니다.

0개의 댓글