[Kotlin] 기본 문법(2) - 심화

1-1. 람다

함수형 프로그래밍의 핵심이라고 할 수 있는 람다는 value처럼 다룰 수 있는 익명함수를 의미한다. 람다는 메소드의 파라미터로 넘겨줄 수 있으며, return값으로 사용할 수도 있다.

val lamdaName:Type = {argumentList->codeBody}

선언과 타입(input,output)을 적고, 파라미터를 적고 어떻게 할지를 적어주는 식으로 동작한다. 예를 들면,

val square = {number:Int->number*number} //방법 1
val square: (Int)->(Int) = {number->number*number} //방법 2

  와 같이 작성하면, Int를 받아서 Int로 반환하는데, number를 받아서 number*number로 반환한다는 것을 알 수 있다. (Int)->(Int)부분이 람다에 대한 타입(input/output)을 나타내고, 중괄호 내에는 람다에 대한 세부 매개변수명이 들어가는 것이다.

println(square(12))
//144

정의한 람다식은 위와 같이 사용하면 된다.

 

람다의 타입 추론이 가능하려면 어느 정도 타입추론이 가능하게끔 설정해주어야 한다.

 

 

 

1-2. 확장함수

클래스에 기능 추가를 위해서 사용한다. 예를 들어, String클래스에 별도의 함수를 추가하고 싶다고 하자. 

val pizzaIsGreat:String.()->String = {this + "Pizza is the best!"}

val str = "i think ";
println(str.pizzaIsGreat());

과 같이 사용하면 String클래스에 람다명으로 지정한 함수를 추가하여 사용할 수 있다.

 

마찬가지로 함수 안에 이런식으로 추가하여 사용할 수도 있다.

fun extendString(name:String, age:Int):String {
    val introduce:String.(Int)->String={"I am ${this} and ${it} years old"};
    return name.introduce(age);
}
println(extendString("kane", 20));

이 때 ${it}은 it 키워드를 사용한 것으로, it은 람다의 파라미터가 하나일 경우 컴파일러가 추론할 수 있게 한다. 여기서 String.(Int)와 같이 int형 파라미터 하나가 넘어오므로 그것이 it으로 들어가게 된다. 

 

 

 

2. Data Class

데이터 클래스란? 말 그대로 데이터를 담는 클래스를 말한다. 

public class User {
	private String name;
    private int age;
    
    public User(String name, int age) {
    	this.name = name;
        this.age = age;
    }
    
    public String getName() {
    	return this.name;
    }
    ...
}

자바로 OOP코딩을 하면서 위와 같이 사람, 차와 같은 객체 클래스를 만들어 본 적이 있을 것이다(데이터 교환을 위해서는 DTO와 같은 객체 클래스에 getter/setter를 설정해서 사용하는 경우가 있다). 이렇게 자바에서는  별도의 비즈니스 로직을 전혀 갖고 있으면서도 getter/setter와 같은 별도의 코드를 필요로 했다.

 

data class Person(var name:String, var age:Int)

코틀린에서는 데이터 클래스라는 방법을 사용하면 이렇게 한 줄로 간편하게 표현할 수 있게 해준다.

이 데이터 클래스는 abstract, open, sealed, inner 선언이 불가능하며, 최소 하나의 파라미터가 존재해야 한다.

이렇게 한 줄로만 선언하면 toString(), equals(), setter/getter, constructor과 같은 함수들을 사용할 수 있게 된다.

 

 

3. Companion Object

자바의 static과 같은 역할을 한다고 생각하면 된다. 

class Book private constructor(val id:Int, val name:String) {

    companion object:IdProvider {

        override fun getId():Int {
            return 444;
        }

        val myBook = "new book";
        fun create() = Book(getId(), myBook);
    }
}

interface IdProvider {
    fun getId():Int;
}

fun main() {
    //val book = Book() //private constructor이므로 사용불가
    val book = Book.Companion.create();
    println("${book.id}, ${book.name}");
}

위에서처럼 Compaion의 이름을 지정하지 않을수도 있고, Companion Object명을 지정해서 사용할 수도 있다.

 

 

4. Object Class

object class는 클래스와 기본적으로 동일한 구조를 가지지만, 싱글턴 패턴의 적용을 위해서 사용된다. 즉 한번만 객체가 생성되게끔 하고, 이후에 생성되는 객체들은 기존 객체를 가져다가 사용하도록 하는 패턴을 코틀린에선 object를 이용하여 간단하게 만들 수 있다. 자바와 다르게 object만 사용하면 thread-safe한 싱글톤 코드를 만들 수 있다.

object CarFactory {
    val cars = mutableListOf<Car>();
    fun makeCar(power:Int):Car {
        val car = Car(power);
        cars.add(car);
        return car;
    }
}

data class Car(val power:Int)

fun main() {
    val car = CarFactory.makeCar(10);
    val car2 = CarFactory.makeCar(200);

    println(car);
    println(car2);
    println(CarFactory.cars.size);
}

CarFactory라는 객체가 새로 계속 생성되는 것이 아니라, CarFactory라는 클래스에서 makeCar라는 메소드를 사용하여 리스트에 Car객체를 생성하여 집어넣고 있다.

'[ Languages ] > Kotlin' 카테고리의 다른 글

[Kotlin] 자바 대신 코틀린 사용하기  (0) 2023.09.01
[Kotlin] 안드로이드 코틀린 연습  (0) 2022.07.06
[Kotlin] 기본 문법(1)  (0) 2022.06.30