모바일&임베디드/안드로이드

[Kotlin] 고급 문법1(Lamda, Class)

차가운오미자 2021. 6. 15. 11:11

1. Lamda

* 람다식은 마치 value 처럼 다룰 수 있는 익명함수이다.

* 최근에 리액트인지 노드js에서 배운 것처럼, 바로 리턴하는 함수를 만들어주는 것

1) 메소드의 파라미터로 넘겨줄 수가 있다. fun maxBy(a: Int)에서 함수를 parameter로 넣어주기

2) return 값으로 사용할 수 있다.

 

* 람다의 기본 선언방식: val lamdaName : Type = {argumentList -> codeBody}

* Type: (parameter) -> (return type)

 

// 람다를 이용해서 제곱을 구하기
// 1. 첫 번째 방법
val square : (Int) -> (Int) = {number -> number*number}
// int 형이 패러미터고 int 형이 반환형이다 {} 안은 리턴 및 함수의 실행코드 내용

// 2. 아래와 같은 방법으로 선언하기도 가능하다.
val square2 = {number : Int -> number*number}

val nameAge = {name : String, age : Int ->
    "my name is ${name} I'm ${age}"
}

 

확장함수

- 확장함수는 기존 클래스에 메소드를 추가하는 것

- 확장함수는 static 메소드이다

- 아래의 예시는 String 클래스에 pizzaIsGreat라는 메소드를 추가해서 사용하는 것임

 

val singASong : String.() -> String = {
    // String 클래스를 확장하는 것임( : String.() 이 부분이
    // 뒤에 -> String 은 반환형을 뜻한다
    this + "Do You Wannna Build A Snowman" // 이게 리턴값이 딤. 리턴이 String이었으니까
    // this는 이 확장함수를 부르는 object를 뜻하고, it은 parameter로 들어간 것
}
// singASong에는 위의 스트링이 저장될 것

// singASong을 부르는 메인 함수
fun main(){
    val a = "She said, "
    val b = "He said, "

    println(a.singASong())
    println(b.singASong())
}

this 와 it

// this 와 it
// it은 패러미터가 하나일때 그 패러미터를 지칭하는 것
fun extendString(name : String, age: Int) : String {
    val introduceMyself : String.(Int) -> String = {
    // parameter은 int로 받는데, 하나니까 it으로 사용 가능
        "I am ${this} and ${it} years old"
    }
    return name.introduceMyself(28)

}

fun main(){
    extendString("jennie", 13)
}

람다의 리턴

// 람다의 리턴
val calculateGrade: (Int) -> String = {
    when(it){
        in 0..40 -> "fail"
        in 41..70 -> "pass"
        in 70..100 -> "perfect"
        // 여기까지 하면 에러뜸 왜냐면 100이상이 들어오거나 0 미만이 들어가면 안되니까
        else -> "Error"
    }
}

 

람다를 이용하는 방식

메소드를 패러미터로 넘겨줄 수 있다.

fun invokeLamda(lamda : (Double) -> Boolean) : Boolean{
    return lamda(5.2343)
    // 람다의 결과값을 invokeLamda의 리턴값으로 쓰겠다
}

fun main(){
    val lamda = { number : Double ->
        number == 4.3212
    }

    println(invokeLamda(lamda)) // 5.2342 == 4.2342?
    println(invokeLamda({it > 3.22})) // 5.2342 > 3.22 ? 
    // it: 하나 들어가는 parameter
    invokeLamda{it > 3.22} // 위에 거랑 같은 것
}

 

2. Class

코틀린에서 class는 파일명과 클래스명이 일치하지 않아도 되고, 한 파일에 여러 클래스를 정의할 수 있다.

1) constructor 선언

class Fruit constructor(val name : String){
    // constructor은 위에 선언
    fun sold(){
        println("fruit is sold")
    }
}

생성자로 객체를 만들 때, 매개변수가 안들어오면 대신 들어가는 기본값을 지정할 수 있다.

class Fruit2 constructor(val name : String = "Anonymous"){
    // default 생성자에 name 값으로 Anonymous를 넣음
    init{
        // instance 만들때 할 동작, 주 생성자로 만들때 자동으로 실행됨
        println("New fruit is created")
    }
    // constructor은 위에 선언

    fun sold(){
        println("fruit is sold")
    }

}

 

* init: 생성자를 만들 때 실행되는 부분이다. 아래 예시에서 볼 수 있는데, init 부분은 constructor보다 먼저 실행된다.

 

* default constructor and secondary cosntructor

자바에서 여러 생성자를 선언할 수 있는 것과 비슷하게 코틀린에서도 여러 생성자를 만들 수 있는데 기본 생성자와 서브 생성자로 나뉜다. 서브 생성자를 만들기 위해 주 생성자가 있어야 하고, 주 생성자의 위임이 필요하다.

 

open class Fruit3 constructor(val name : String = "Anonymous"){

    constructor( name : String, age : Int) : this(name){
        // 주생성자의 위임을 받아야 함: this(name)
        println("my name is ${name}, ${age}years old")
    }
    // constructor보다 init 부분이 먼저 실행이 된다.

    init{
        // instance 만들때 할 동작, 주 생성자로 만들때 자동으로 실행됨
        println("New fruit is created")
    }
    // constructor은 위에 선언

    open fun sold(){
        println("fruit is sold")
    }

}

fun main(){
    val cherry = Fruit3( "Cherry", 1 )
}

2) 상속

class SummerFruits : Fruit3(){
    // 이런식으로 상속하는데, 상속을 받으려면 parent을 open해줘야 함
    // java에서 overriding하듯이 부모 함수를 자식 함수에게 override하려면
    override fun sold(){
        // 이 클래스에서 특별하게 사용하고 싶을 때 오버라이딩
        // 오버라이딩이 바로는 안되고 역시 부모 함수가 open되어 있어야 함
        super.sold()
        println(" in summer")
        println("this fruit is: $name")
    }
}

* open: 약간 자바의 public 개념과 비슷. 외부에서 접근할 수 있도록

* 오버라이딩: 이 클래스에서 부모 클래스의 함수를 새로 정의하고 싶을 때 한다. 오버라이딩 하려는 함수가 부모 클래스에서 open되어 있어야 한다.

* super: 부모 클래스를 지칭

 

이렇게 하고

fun main(){
    val watermelon = SummerFruits("Watermelon", 1)
    watermelon.sold()
}

이러면 에러가 뜬다. Too many arguments for public constructor SummerFruits() in ... 이라고 뜨는데, 생성자는 상속이 안되는 것 같다?

* 생성자 상속

class SummerFruits : Fruit3{

    // 생성자 상속 필요
    constructor(name: String): super(name)
    constructor(name: String, age : Int): super(name, age)

    override fun sold(){
        super.sold()
        println(" in summer")
        println("this fruit is: $name")
    }
}

생성자 상속 선언이 필요하며, 주생성자가 상속되지 않으면 부생성자를 받을 수 없다.