[Kotlin] 코틀린 기본 문법

donghyeok·2023년 3월 28일

Kotlin

목록 보기
2/3

코틀린 기본 문법

1. 변수

  • 기본 선언 방법
    - val : 자바의 final 키워드처럼 초기화 후에 변경X
    - var : 가변 변수이므로 초기화 후에 변경 가능

    (val|var) 변수명 : 반환 타입 = 변수에 담을 값

  • 변수 선언
    - 타입은 생략 가능 (추론)
    - 선언 -> 할당(지연 할당)의 경우 타입 명시 필수

    val a : Int = 1

  • 탑-레벨에 선언 가능

2. 함수

  • 기본 선언 방법

    fun 함수명(인자: 타입, 인자 : 타입) : 반환 타입 { }

  • 함수 본문은 다음처럼 표현식이 될 수 있다.
    - 이러한 경우 반환 타입이 없어도 컴파일러가 적절한 타입을 추론한다. (본문이 있으면 불가)

    fun sum(a: Int, b: Int) : Int = a + b

  • 반환값이 없는 경우 자바의 void처럼 Unit이 반환 타입이 된다. (생략 가능)
  • 디폴트 파라미터 기능 존재

    fun greeting(message:String = "hello") {}

  • 함수 호출 시, 파라미터명을 넣어서 인자를 주입할 수 있다 (네임드 아규먼트)

    greeting(message = "안녕")

3. 흐름제어

  • if .. else
    - 코틀린의 if..else는 표현식이다. (값을 반환할 수 있다.)
    - 코틀린은 삼항 연산자가 없다. (if..else가 표현식이라 불필요)
  • when
    when (대상변수) {
        조건1, 조건2 -> 참인 경우 실행
        조건3 -> 참인 경우 실행
        else -> 참인 조건이 없을 경우 실행
    }
    • 자바의 switch문과 유사하다.
    • 자바의 switch에서 break를 유의해야하는 점을 개선
    • when구문의 경우 표현식이기 때문에 값 반환이 가능하다.
  • for loop
    for (i in 0..3) { }         // 0 <= i <= 3 반복
    for (i in 0 until 3) { }    // 0 <= i < 3 반복
    for (i in 0..6 step 2) { }  // 2씩 증가
    for (i in 3 downTo 1) { }   // 3 >= i >= 1 1씩 감소
    for (i in numberList) { }   // 배열값 반복    
    • 기본적으로 자바의 foreach와 유사하며 사용법은 위와 같다.
  • while loop
    - 자바의 while문과 동일하다.

4. 널 안정성

  • 널 참조의 위험성
    - 모두 알고 있듯이 NPE는 자바에서 치명적인 오류이다.
    - 자바에서는 대안으로 Optional을 지원하기 시작했다.
    - 하지만, 객체 생성에 따른 오버헤드가 발생하고, 컴파일 단계에서 null 가능성을 검사X
  • 코틀린에서 NPE를 해결하는 다양한 방법
    - 코틀린은 언어적 차원에서 NPE 발생 가능성을 제거
    - 코틀린의 타입은 기본적으로 non-null타입으로 null을 허용하지 않음
    - 코틀린은 null을 허용하는 nullable 타입을 제공한다. val a : String? = null
    - nullable 참조에 대한 접근은 안전 연산자를 사용한다. a?.length
    - 엘비스 연산자를 이용해 null이 아닌 경우 특정값을 사용하도록 한다. val b = a?.lenth ?: 0
  • 코틀린에서도 NPE가 발생할 순 있다.
    1. 단언 연산자를 사용하여 not Null임을 강제할 때 val d = c!!.length
    2. 자바와 상호운용하는 경우 자바에서 NPE를 유발하는 코드를 코틀린에서 사용할 떄

5. 예외처리

  • 코틀린의 모든 예외 클래스는 최상위 예외 클래스인 Throwable을 상속한다.
  • 코틀린에서는 자바의 Exception 계층을 코틀린 패키지로 래핑한다.
  • 코틀린에서는 체크드 익셉션을 꼭 try .. catch로 감싸지 않아도 된다.
  • 원하는 경우에 try .. catch .. finally 구문을 사용할 수 있다.
  • 코틀린의 try .. catch .. finally 구문 역시 표현식이다.

6. 클래스와 프로퍼티

  • 클래스
    - class 키워드를 사용하여 클래스 선언
    - 코틀린의 클래스는 본문 생략 가능
    - 코틀린의 생성자는 기본 생성자와 하나 이상의 보조 생성자가 존재할 수 있다.
    - 코틀린에서 클래스 프로퍼티를 선언할 때 후행 쉼표를 사용할 수 있다. (git diff에서 유용)
  • 프로퍼티
    - 프로퍼티에 var, val 모두 사용 가능하다.
    - 프로퍼티를 수정하거나 사용하려면 참조를 사용하면 된다.
  • getter, setter
    - 코틀린은 var로 선언된 프로퍼티의 getter, setter를 자동으로 생성한다.
    - val로 선언된 프로퍼티는 getter만 존재한다.
    - 또한 아래와 같이 커스텀 getter를 만들 수 있다.
    class Coffee {
    	val brand: String
       		get() = "스타벅스" //커스텀 getter
        var quantity: Int = 0
       		set(value) {
               		if (value > 0) {
                       	field = value
                    }
            }
    }
    - 또한 위와 같이 var로 선언된 프로퍼티에 한하여 커스텀 setter를 만들 수 있다.
    - 코틀린은 getter, setter에서 field라는 식별자를 사용해 필드의 참조에 접근하는데 이를 Backing Field에 접근한다고 한다.
    - 만일 field가 존재하지 않으면 값을 할당할 때 무한 재귀가 발생한다. (위에서 field 대신 quantity 사용)

7. 상속

  • 자바는 기본적으로 상속을 막기 위해 final키워드 사용 가능
  • 객체 지향의 언어의 지향점 중에 상속을 목적으로 하지 않는 클래스는 상속을 막아라라는 것이 존재
  • 코틀린의 클래스는 기본적으로 상속이 불가하고 꼭 필요한 경우 open 키워드로 상속을 허용
  • 하위 클래스에서 상위 클래스를 상속하려면 클래스 뒤에 :을 추가하고 상위 클래스 입력
    open class Dog
    class Bulldog : Dog()
  • 함수나 프로퍼티를 재정의 할때도 마찬가지로 open을 사용해 오버라이드를 허용해야함.
  • 오버라이드 된 함수나 프로퍼티는 기본적으로 open되어 있으므로 final 키워드로 하위 클래스 오버라이드를 막을 수 있음.
  • 하위 클래스에서 상위 클래스의 함수나 프로퍼티를 접근할 때 super 키워드 사용 가능
  • abstract 키워드를 통해 추상 클래스도 사용 가능

8. 인터페이스

  • 코틀린 역시 자바처럼 interface 키워드를 사용해 인터페이스 정의 가능
  • 인터페이스 내의 함수는 본문이 있으면 구현 함수, 본문이 없으면 추상 함수가 된다.
    interface Cart {
    	fun add(num: Int)   //추상함수 -> 구현 필요 
        fun rent() {       //구현함수 -> 구현 불필요 
       	 ...
        }
    }
  • 클래스는 하나 이상의 인터페이스를 구현할 수 있다.
  • 이때 동일한 시그니처를 가진 함수가 있는 경우 super<인터페이스명>을 통해 특정 인터페이스를 선택할 수 있다.
  • 두 인터페이스에 구현을 가진 동일 시그니처 디폴트 함수가 있는 경우 하위 클래스에서 직접 구현해야 한다.

9. 열거형 (Enum)

enum class PaymentStatus(val label: String) : Payable {
		UNPAID("미지급") {
 			override fun isPayable() = true	
 		},
     	PAID("지급완료"){
 			override fun isPayable() = true	
 		}, 
     	FAILED("지급실패"){
 			override fun isPayable() = true	
 		},
     	REFUNDED("환불"){
 			override fun isPayable() = true	
 		},
}
  • 자바처럼 enum 키워드를 사용해 열거형을 정의할 수 있다.
  • enum 클래스도 클래스이므로 생성자와 프로퍼티를 정의할 수 있다.
  • 만일 위처럼 abstract 함수를 가지는 인터페이스를 구현한다면 각각의 상수는 익명 클래스 형태로 abstract 함수를 구현할 수 있다.
for (status in PaymentStatus.values()) {
	println("${status.name}, ${status.label}, ${status.ordinal}")
}
  • enum 클래스의 상수를 나열하려면 values() : Array<EnumClass> 함수를 사용한다.
  • 위처럼 기본 제공하는 2개의 프로퍼티(name, ordinal)을 사용해 이름이나 순서를 얻을 수 있다.

0개의 댓글