관리 메뉴

너와 나의 스토리

[Kotlin] 코틀린 기초1 - 함수, 변수, 클래스, property, enum, when 본문

Programming Language/Kotlin

[Kotlin] 코틀린 기초1 - 함수, 변수, 클래스, property, enum, when

노는게제일좋아! 2021. 6. 10. 21:19
반응형

1. 함수와 변수 

함수

  • 코틀린 함수는 내부에 아무 효과가 없어서 오로지 인자에 의해서만 반환 값이 결정된다.
    • 이런 함수를 종종 순수 함수(pure function)라고 부른다.
    • 이는 항상 같은 인자에 대해 같은 결과를 내놓는다.
  • main 함수는 다음과 같이 생겼다.
fun main(args: Array<String>) {

}
  • Hello world를 출력해보자.
    • main 함수에 println()를 이용해 'hello world' string을 출력할 수 있다.
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util.println

fun main(args: Array<String>) {
    println("Hello World!") // output: Hello World!
}
  • 이번에는 두 값을 받아, 둘 중 큰 값을 반환하는 함수를 만들어보자.
    • 변수는 다음과 같이 정의할 수 있다.
      • fun '메서드 이름'('변수 이름': '변수 타입'): 반환형 {}
    • max1(), max2(), max3() 모두 동일하게 동작하는 함수이다.
    • max3처럼 코틀린은 간결하게 함수를 표현할 수 있다.
fun max1(a: Int, b: Int): Int {
    if (a > b)
        return a
    else
        return b
}

fun max2(a: Int, b: Int): Int {
    return if (a > b) a else b
}

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

fun main(args: Array<String>) {
    println(max1(2, 3)) 
    println(max2(2, 3))
    println(max3(2, 3))
}

 

변수

  • 코틀린에서는 타입 지정을 생략하는 경우가 흔하다. 
  • 하지만 원한다면 타입을 명시할 수도 있다.
  • 예:
val strVal = "string"
val intVal = 42

val intVal2: Int = 42
  • 하지만, 초기화 식을 사용하지 않고 변수를 선언하려면 변수 타입을 반드시 명시해야 한다.
val intVal: Int
intVal = 42
  • 변경 가능한 변수와 변경 불가능한 변수
    • 변수 선언 시 사용하는 키워드는 다음과 같이 2가지가 있다.
      • val
        • 변경 불가능한(immutable) 참조를 저장하는 변수이다.
        • val로 선언된 변수는 일단 초기화하고 나면 재대입이 불가능하다.
        • 자바로 말하면 final 변수에 해당한다.
      • var
        • 변경 가능한(mutable) 참조다. 
        • 언제든지 변수의 값을 바꿀 수 있다. 
        • 자바로 말하면 일반 변수에 해당한다.
  • val 변수는 블록을 실행할 때 정확히 한 번만 초기화돼야 한다. 하지만 어떤 블록이 실행될 때 오직 한 문장에서만 초기화됨을 컴파일러가 확인할 수 있다면 조건에 따라 val 값을 다른 여러 값으로 초기화할 수도 있다.
val message: String
if (canPerformOperation()) {
	message = "Success"
}
else {
	message = "Failed"
}
  • val 참조 자체는 불변일지라도 그 참조가 가리키는 객체의 내부 값은 변경될 수 있다.
val languages = arrayListOf("Java")
languages.add("Kotlin")

println(languages)  // output: [Java, Kotlin]

 

문자열 형식 지정

  • 문자열 리터럴의 필요한 곳에 변수를 넣을 수 있다.
val world = "World"
println("Hello $world") // output: Hello World

val helloWorld = arrayListOf("Hello")
helloWorld.add("World")
println("${helloWorld[0]} ${helloWorld[1]}") // output: Hello World

println("Hello ${if (helloWorld.size>1) helloWorld[1] else "everyone"}") // output: Hello World

 

 

2. 클래스와 프로퍼티

클래스

  • 간단한 Java 클래스 Person이 있다.
public class Person {
    private final String name;

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

    public String getName() {
        return name;
    }
}
  • 이를 Kotlin 클래스로 변환하면 다음과 같다.
    • 코틀린의 기본 가시성은 public이다.
class Person(val name: String)

 

프로퍼티(Property)

  • 자바에서는 필드와 접근자를 한데 묶어 프로퍼티라고 부른다.
    • 접근자 메서드: getter, setter
  • 클래스 안에서 변경 가능한 프로퍼티 선언해보자
class Person(
    val name: String, // getter만 만듦
    var isMarried: Boolean // setter, getter 다 만듦
)

fun main(args: Array<String>) {
    val person = Person("Bob", true)
    println(person.name) // output: Bob
    println(person.isMarried) // output: true

//    person.name="John" -> compile error(val은 변경 불가)
    person.isMarried=false
    println(person.isMarried) // output: false
}

 

코틀린 소스코드 구조: 디렉터리와 패키지

  • 자바처럼 코틀린도 파일의 맨 앞에 package 문을 넣을 수 있다.
  • 그러면 그 파일 안에 있는 모든 선언(클래스, 함수, 프로퍼티 등)이 해당 패키지에 들어가고, 같은 패키지에 속해 있다면 다른 파일에서 정의한 선언일지라도 직접 사용할 수 있다.
  • 반면, 다른 패키지에 정의한 선언을 사용하려면 import를 통해 선언을 불러와야 한다.

 

3. 선택 표현과 처리: enum과 when

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

 

enum 클래스

  • 자바에서는 다음과 같이 간단하게 사용한다.
    • enum '클래스명' { }
  • 코틀린에서는 여기에 class라는 말이 더 붙는다.
    • enum class '클래스명' { } 
  • 자바와 마찬가지로 enum은 단순히 값만 열거하는 존재가 아니다. enum 클래스 안에도 프로퍼티나 메서드를 정의할 수 있다. 
  • 예:
    • 코틀린에서 유일하게 세미콜론(;)이 필수인 부분을 볼 수 있다.
    • enum 클래스 안에 머서드를 정의하는 경우 반드시 enum 상수 목록과 메서드 정의 사에 세미콜론을 넣어야 한다.
enum class Color(
    val r: Int, val g: Int, val b: Int  // 상수의 프로퍼티를 정의
) {
    RED(255, 0, 0), ORANGE(255, 165, 0),  // 각 상수를 생성할 때 그에 대한 프로퍼티 값을 지정
    YELLOW(255, 255, 0), GREEN(0, 255, 0);

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

fun main(args: Array<String>) {
    println(Color.RED.rgb())
}

 

when으로 enum 클래스 다루기

fun getMnemonic(color: Color) =
    when (color) {
        Color.RED -> "Richard"
        Color.ORANGE -> "Of"
        Color.YELLOW -> "York"
        Color.GREEN -> "Gave"
        Color.BLUE, Color.INDIGO, Color.VIOLET -> "color"
    }

fun main(args: Array<String>) {
    println(getMnemonic(Color.RED))  // output: Richard
    println(getMnemonic(Color.INDIGO))  // output: color
}

 

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

  • 자바의 경우 분기 조건에 상수(enum 상수나 숫자 리터럴)만을 사용할 수 있지만, 코틀린 when의 분기 조건은 임의의 객체를 허용한다.
fun mix(c1: Color, c2:Color) =
    when (setOf(c1, c2)){
        setOf(Color.RED, Color.YELLOW) -> Color.ORANGE
        setOf(Color.YELLOW, Color.BLUE) -> Color.GREEN
        setOf(Color.BLUE, Color.VIOLET) -> Color.INDIGO
        else -> throw Exception("Dirty color")
    }
fun main(args: Array<String>) {
    println(mix(Color.BLUE, Color.YELLOW)) // output: GREEN
}
  • 위 예처럼 setOf를 사용해서 두 색의 조합을 찾는 경우, 입력이 들어올 때마다 여러 Set 인스턴스를 생성한다. 이 함수가 아주 자주 호출되는 경우 불필요한 가비지 객체가 늘어나 비효율적이다. 
  • 이를 다음과 같이 수정할 수 있다.
    • 성능은 향상되지만 가독성은 떨어진다
setOf(Color.RED, Color.YELLOW) -> Color.ORANGE
==
(c1==RED && c2==YELLOW) || (c1==YELLOW && c2=RED) -> Color.ORANGE

 

 

 

출처:

- [Kotlin IN ACTION]

반응형
Comments