[Kotlin] 코틀린 기초(1)

sw·2021년 12월 26일
0

1. 함수

  • 함수를 선언할 땐 fun 키워드를 사용한다.
  • 함수를 최상위 수준에 정의할 수 있다. 즉, 자바와 달리 클래스 안에 함수를 넣어야 할 필요가 없다.
fun max(a: Int, b: Int): Int {
    return if (a > b) a else b
}

-> 코틀린에서 if문은 statement가 아니라 expression이다.

expression : 값을 만들어내며 다른 expression의 하위 요소로 계산에 참여할 수 있다.

statement : 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며 아무런 값을 만들어내지 않는다.

-> 자바에서는 모든 제어구조가 statement이지만 코틀린에서는 Loop를 제외한 대부분의 제어 구조가 expression이다. 반면 대입문의 경우 자바에서는 expression이였지만 코틀린에서는 statement이다.

- 식(expression)이 본문인 함수

위의 함수를 다음과 같이 간결하게 표현할 수 있다.

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

본문이 중괄호로 둘러싸인 함수를 블록이 본문인 함수라 부르고, 등호와 식으로 이뤄진 함수를 식이 본문인 함수라고 부른다. 코틀린에서는 식이 본문인 함수가 자주 쓰인다.
여기서 반환 타입을 생략하면 더 간단히 함수를 만들 수 있다.

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

반환타입이 생략가능한 이유는 식이 본문인 함수의 경우 굳이 사용자가 반환 타입을 적지 않아도 컴파일러가 함수 본문 식을 분석해서 식의 결과 타입을 함수 반환 타입으로 정해준다. 이런 기능을 타입 추론이라고 한다.


2. 변수

변수 선언 시 사용하는 키워드는 다음과 같은 2가지가 있다.

  • val: 변경 불가능한 참조를 저장하는 변수
  • var: 변경가능한 참조를 저장하는 변수

타입을 지정하지 않으면 컴파일러가 초기화 식을 분석해서 초기화 식의 타입을 변수 타입으로 지정한다.

val a = 1
val b: Int = 2

기본적으로 모든 변수를 val키워드를 사용해 불변 변수로 선언하고, 나중에 꼭 필요한 때에만 var로 변경하자.
val 변수는 블록을 실행할 때 정확히 1번만 초기화돼야 한다. 하지만 어떤 블록이 실행될 때 오직 한 초기화 문장만 실행된다는 걸 컴파일러가 확인할 수 있다면 조건에 따라 val 값을 다른 여러 값으로도 초기화할 수 있다.

val message: String

if (isTrue()) {
    message = "참"
} else {
    message = "거짓"
}

val 참조 자체는 불변이라도 그 참조가 가리키는 객체의 내부 값은 변경될 수 있다.

val languages = arrayListOf("Java")
languages.add("Kotlin")

또한 var 키워드를 사용하면 변수의 값을 변경할 수 있지만 변수의 타입은 고정돼 바뀌지 않는다.

var answer = 42
answer = "HI"	// 컴파일 오류 발생

- 문자열 템플릿
코틀린에서도 변수를 문자열 안에 사용할 수 있는데, 변수 앞에 $를 추가해주면 된다. 복잡한 식도 중괄호로 둘러싸서 문자열 템플릿 안에 넣을 수 있다. $문자를 문자열에 넣고 싶으면 \를 사용해 $를 이스케이프시켜야 한다.

val name = "Kotlin"
println("Hello, $name!")

val a = 3
val b = 4
println("sum: ${a+b}")
println("max: ${if(a>b) a else b}")

3. 클래스

class Person(val name: String)

이런 유형의 클래스를 값 객체(Value Object)라고 부른다. 코틀린의 기본 visibility modifier는 public이다. 여기서 visibility modifier는 "누구에게 공개할 것인가?" 정도로 이해하면 된다.

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

자바에서는 데이터를 field에 저장하며, 멤버 필드의 access modifier는 보통 private이다. 클래스는 자신을 사용하는 클라이언트가 그 데이터에 접근하는 통로로 쓸 수 있는 접근자 메소드(accessor method)를 제공한다.
ex) getter, setter 메소드

필드와 접근자를 한데 묶어 property라고 한다.
코틀린은 property를 언어 기본 기능으로 제공하며, 자바의 필드와 접근자 메소드를 완전히 대신한다. 클래스에서 property를 선언할 때는 변수를 선언할 때와 마찬가지로 val이나 var를 사용한다. val은 읽기 전용, var은 변경 가능하다.

class Person(
    val name: String,// 읽기 전용 property
                     // 코틀린은 (비공개)필드와 (공개)getter를 만들어낸다.
    
    var age: Int     // 쓸 수 있는 property
                     // (비공개)필드, (공개)getter, (공개)setter를 만들어낸다.
)

fun main(){
    val person = Person("Bob",20)
    println(person.age) 
}
// property 이름을 직접 사용해도 코틀린이 자동으로 getter를 호출해준다. 
// setter도 마찬가지 방식으로 동작한다.

대부분의 propertry에는 그 property 값을 저장하기 위한 필드가 있다. 이를 backing field라고 한다. 원한다면 property 값을 그때그때 계산할 수도 있다.

- 커스텀 접근자

class Rectangle(val height: Int, val width: Int) {
    val isSquare: Boolean
        get() {
            return height == width
        }
}

isSquare property는 자체 값을 저장하는 필드가 필요 없다. 클라이언트가 property에 접근할 때마다 getter가 property 값을 매번 다시 계산한다.
파라미터가 없는 함수를 정의하는 방식 vs 커스텀 게터를 정의하는 방식 모두 구현이나 성능상 차이는 없다. 차이가 나는 부분은 가독성뿐이다.
일반적으로 클래스의 특성을 정의하고 싶다면 property로 그 특성을 정의해야 한다.

profile
끄적끄적

0개의 댓글