kotlin 개념 복습 정리

49642 단어 kotlinkotlin

1. 함수

// 리턴 없으면, 타입 없어도 됨
fun helloWorld() {
    println("hello world!")
}

//리턴 타입이 있는경우
//코틀린에서는 자바와 달리, 타입을 뒤에 적음
fun add(a: Int, b: Int): Int {
    return a + b
}

2. val vs var

//val = value
fun hi() {
    val a: Int = 10 //고정인 변수
    var b: Int = 9 //바꿀수 있는 변수
    var e: String

    b = 100 //var라 변경가능

    //자동 타입 추론
    val c = 100
    var d = 100
    var name = "mangyun"
}

3. String Template

fun string() {
    val name = "mangyun"
    val lastName = "Lee"
    println("my name is ${name + lastName}")//$ 표시로 변수를 대입가능
    println("this is 2\$a") //이스케이프 문자. 달러 출력
}

4. 조건문

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

fun maxBy2(a: Int, b: Int) = if (a > b) a else b //코틀린에서는 이렇게 쓸수도 있음

fun checkNum(score: Int) {
    when (score) {//다른 언어의 case문같은, when문이 있음
        0 -> println("this is 0")
        1 -> println("this is 1")
        2, 3 -> println("this is 2 or 3")
        else -> println("I don't know")
    }

    var b = when (score) {// 이렇게 리턴식으로 바로 쓸 수도 있음, 하지만 무조건 else를 써줘야함
        1 -> 1
        2 -> 2
        else -> 3
    }
    println("b : ${b}")

    when (score) { //범위 지정도 가능
        in 90..100 -> println("you are genius")
        in 10..80 -> println("not bad")
        else -> println("okay") //80~90 사이, 위와는 달리 굳이 else 안써도 됨
    }
}

Expression vs Statement

expression - 뭔가 과정을 거쳐서 값이 리턴되는 것

statement - 그냥 단순한 실행

  • 코틀린의 모든함수는 리턴이 없더라도 Unit을 반환해서 expression이다.
  • 자바는 void같이 리턴값이 없다면 statement이다.

5. Array and List

  • Array는 기본적으로 크기가 정해짐
  • 일반List - 못바꿈, MutableList - 수정가능
fun array() {
    val array = arrayOf(1, 2, 3)
    val list = listOf(1, 2, 3)

    val array2 = arrayOf(1, "d", 3.4f)
    val list2 = listOf(1, "d", 11L)

    array[0] = 3
    var result = list.get(0) //일반list는 위 array처럼은 바꿀 수 없고, 가져올 수만 있다.

    val arrayList = arrayListOf<Int>() //arrayList같은 배열들은 애초에 주소로 움직이기때문에, var에서 val로 바꿀 수 있다.
    arrayList.add(10)
    arrayList.add(20)
    //arrayList = arrayListOf() 이렇게 재할당이 안됨
}

6. 반복문 for / while

fun forAndWhile() {
    val students = arrayListOf("mangyun", "jame", "jenny", "jennifer")

    for (name in students) { // 총 4명 반복
        println("${name}")
    }

    for ((index, name) in students.withIndex()) {//index를 같이 사용할 수도 있음
        println("${index + 1}번째 학생 : ${name}") //1번째 학생 : mangyun , ..등등
    }

    for (i in 1..10 step 2) {
    } //1, 3, 5, 7, 9

    for (i in 10 downTo 1) {
    } //10부터 1까지 내림차순

    for (i in 1 until 100) {
    } //100을 포함하지 않음, 총 99번

    var index = 0
    while (index < 10) { //0부터 9까지만
        index++
    }
}

7. Nullable / NonNull

자바와 코틀린의 가장 큰 차이

  • NPE : NULL pointer Exception - 무조건 런타임 시점인 실행을 해야 오류를 잡을 있는 자바
  • 그래서 컴파일에서 오류를 잡을 수 있게 사용하는 ?형식의 코틀린
fun nullcheck() {
    var name = "mangyun" //null이면 안되는 타입, 타입생략 가능

    var nullName: String? = null //String같은 nonNull에 null넣으면 에러. 그래서 ?을 붙임, 타입생략못함

    var nameInUpperCase = name.toUpperCase() //정상

    var nulNameInUpperCase = nullName?.toUpperCase() //만약에 null이 아니면 대문자로, null이면 그대로 null반환

    // ?: - 엘비스 연산자 (엘비스프레슬리 앞머리 모양이 닮아다고 해서.. 귀엽긴하네)
    val lastName: String? = null
    val fullName =
        name + " " + (lastName ?: "NO lastName")//만약에 null이면 NO lastName으로 리턴, 그냥 기본값이라고 생각하자

    //!! - 이거 null 아니라고 보증하는 표시, 편하긴하지만 웬만하면 지양하자.
    fun ignoreNulls(str: String?) { //str이 null일수도 있음
        val mNotNull: String = str!! //하늘이 두쪽나도 절대로 null아니라고 내가 정함
        val upper = mNotNull.toUpperCase()//null아니라 했으니, 굳이 ? 안써도 됨

        val email: String? = "[email protected]"
        email?.let { //let함수는 null이 아닐때 실행됨
            println("my email is ${email}")
        }
    }
}

8. class

//class Human constructor(val name : String) {
open class Human(val name: String = "Anonymous") { //바로 기본값을 줄 수도 있음

//    //자바라면 이렇게 헀을 생성자, 코틀린은 위에 constructor하고 아래에 name 할당, 둘다 생략가능
//    Human(){
//
//    }

//    val name = name

    //주생성자 - 무조건 class 쓸때마다 제일 먼저 실행
    init {
        println("New human has been born!!")
    }

    //부생성자 - 항상 this로 주생성자의 위임을 받아야 함
    constructor(name: String, age: Int) : this(name) {
        println("my name is ${name}. ${age}years old")
    }

    fun eatingCake() {
        println("This is so yummmyyy~~")
    }

    open fun singASong() {
        println("lalala")
    }
}

class 상속

//코틀린의 class들은 기본적으로 final이기 때문에, 해당 부모 클래스를 open시켜야 상속할 수 있음.
class Korean : Human() {

    //오버라이딩 - 상속받는 기능을 여기서만 다르게 사용하는 것. 예를들어 부모는 외국노래를 부르는데, 나는 한국노래를 부르고 싶을 때
    override fun singASong() {
        super.singASong() //원래의 singASong도 사용해 lalala 출력
        println("라라라")
        println("my name is : ${name}") //부모의 기본값 Anonymous도 가져옴
    }
}


fun main() {
    val human = Human("mangyun")
    val stranger = Human()

    human.eatingCake()

    println("this human's name is ${human.name}") //mangyun 출력
    println("this human's name is ${stranger.name}") //기본값 Anonymous 출력
    val mom = Human("Kuri", 52)

    val korean = Korean()
    korean.singASong() //아래처럼 출력됨
    //New human has been born!!
    //lalala
    //라라라
    //my name is : Anonymous
}

9. lamda

람다식은 우리가 변수처럼 다룰 수 있는 익명함수

1) 메소드의 파라미터로 넘겨줄 수가 있다. fun maxBy(a : Int)
2) 리턴 값으로 사용할 수가 있다.

// 람다의 기본 정의
// val lamdaName : Type = {argumentList -> codeBody}
val square = { number: Int -> number * number } //타입추론이 가능하게 Int 해줘야함
val nameAge = { name: String, age: Int -> //두 개를 동시에 넘기기도 가능
    "my name is ${name} I'm ${age}"
}

fun main() {
    println(square(12)) //144
    println(nameAge("mangyun", 99))//my name is mangyun I'm 99
    val a = "anna said "
    println(a.pizzaIsGreat())//anna said Pizza is the best!

    println(extendString("ariana", 27))//I am ariana and 27 years old
    println(calculateGrade(101))//error


    val lamda = { number: Double ->
        number == 4.3213
    }

    println(invokeLamda(lamda))//false
    println(invokeLamda({ it > 3.22 }))//true
    println(invokeLamda{ it > 3.22 })//true, 마지막 파라미터가 람다식일 때 소괄호 생략, 굉장히 많이 쓰이는 표현


}

확장함수

val pizzaIsGreat: String.() -> String = {
    this + "Pizza is the best!" //this는 String, ()이기때문에 전체 리턴
}

fun extendString(name: String, age: Int): String {
    val introduceMyself: String.(Int) -> String =
        { "I am ${this} and ${it} years old" } //this는 String, 입력파라미터가 하나일때 it은 Int
    return name.introduceMyself(age)
}

// 람다의 리턴
val calculateGrade: (Int) -> String = {
    when (it) {
        in 0..40 -> "fail"
        in 41..70 -> "pass"
        in 71..100 -> "perfect"
        else -> "error" //String 리턴을 못하면 에러를 뜨기때문에, 범위이외의 else 써줘야함
    }
}

//람다를 표현하는 여러가지 방법
fun invokeLamda(lamda: (Double) -> Boolean): Boolean {
    return lamda(5.2343)
}

10. data class

  • toString(), hashCode(), equals(), copy()가 간단히 만들어진다.
  • 자바와는 달리, 여러개의 data class 만들 수 있어서 편하다.
data class Ticket(val companyName : String, val name : String, var date : String, var seatNumber : Int)

class TicketNormal(val companyName : String, val name : String, var date : String, var seatNumber : Int)

fun main(){
    val ticketA = Ticket("koreaAir", "mangyun", "2021-02-15", 14)
    val ticketB = TicketNormal("koreaAir", "mangyun", "2021-02-15", 14)

    println(ticketA) //Ticket(companyName=koreaAir, name=mangyun, date=2021-02-15, seatNumber=14), 보기편하게 객체내용이 바로 보임
    println(ticketB) //com.leemyeongyun.kotlinpractice1.TicketNormal@6fadae5d, 보기 불편하게 메모리 주소값이 보임
}

11. companion object

  • 자바의 static 역할을 한다.
class Book private constructor(val id : Int, val name : String){

    companion object BookFactory :IdProvider { //private된 요소들을 가져올 수 있다. 이름지정가능

        override fun getId(): Int {
            return 444
        }

        val myBook = "new book" //property도 쓸 수 있음

        fun create() = Book(getId(), myBook)
    }
}

interface IdProvider { //BookFactory가 상속할 수 있게 interface 하나 만들어봄
    fun getId() : Int
}

fun main(){
    val book = Book.create()
    val bookId = Book.BookFactory.getId()
    println("${book.id} ${book.name}")
}

12. Object

클래스와 다르게, 실행이 될때 딱 한번만 만들어진다. = Singleton Pattern

1) 싱글턴 클래스를 만들 때 사용
2) 익명 클래스 객체를 만들 때 사용

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

data class Car(val horsePower: Int)

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

    println(car) //Car(horsePower=10)
    println(car2) //Car(horsePower=200)
    println(CarFactory.cars.size.toString())//2
}

좋은 웹페이지 즐겨찾기