세상은 모험을 두려워 하지않은 자의 것이다~~!

Java 개발자가 Kotlin 을 공부하면서.. 끄적인 노트입니다.

 

Lambda

/*
    Lambda
    고차 함수 (High order function) : 함수를 자료형이나, 객체처럼 인자로 받거나 리턴 할수 있는 함수 (일반적으로 callback 함수라고도 함)

    일반적으로 Lambda 사용법 (Java8 부터 지원하는 Lambda 식과 유사함)
    (인자타입1, 인자타입2) -> 반환형  
    () -> Unit // argument가 없고, void
    (Int, Int) -> Int // argument를 Int, Int를 받고 Int type을 반환
 */

fun testFunc1(func: () -> Unit) { // return type 이 없는 lambda 함수를 Argument로 받을 수있는 함수
    func()
}

fun testFunc2(num: Int, func: () -> String) { // String을 return하는 lambda 함수를 Argument로 받을 수 있는 함수
    println("Argument num : '${num}'")
    var callback = func()
    println(callback)
}

fun testLambdaExec1() {
    // argument가 없고 return 값이 없는 고차 함수를 전달
    testFunc1 { println("Argument가 없고, 리턴값이 없는 고차함수") }

    /* 
        실행결과
        Argument가 없고, 리턴값이 없는 고차함수
     */

    // argument가 있고, multiple line에 return value가 있는 고차함수를 전달
    testFunc2(100) {
        println("Argument가 있고, 리턴값이 있는 고차함수")
        "Return!!!"
    }

    /* 실행결과
        Argument num : '100'
        Argument가 있고, 리턴값이 있는 고차함수
        Return!!!
     */
}


// ===================

fun testFunc3(func: (Int, Int) -> Int) {
    println("Argument가 2개, Return 값이 있는 고차함수 처리 결과 : ${func(10, 30)}")
}


fun sumTest(a: Int, b: Int): Int {
    return a + b
}

fun testLambdaExec2() {
    testFunc3 { a, b -> a + b } // Argument가 2개, Return 값이 있는 고차함수 처리 결과 : 40
    testFunc3(::sumTest) // 미리 정의된 함수를 전달 할수도 있다. (argument와 return type 이 일치 해야함)
}


// ===================

fun testFunc4(func: (Int) -> String) {
    println("결과는 : ${func(10)}")
}

fun testLambdaExec3() {
    testFunc4 {
        println("단일 매개변수일 경우 암묵적으로 it을 keyword로 매개변수에 접근 할 수 있다. it : '${it}'")
        it.toString()
    }
}

// ================

fun testLambdaExec4() {
    val sumTest1: (Int, Int) -> Int = { a, b -> a + b }
    val sumTest2: (Int, Int) -> Int = ::sumTest // 미리 정의된 함수를 변수에 담을 수 있다.

    println("sumTest1 : ${sumTest1(10, 20)}")
    println("sumTest2 : ${sumTest2(20, 30)}")
    println("sumTest : ${sumTest(30, 40)}")
    /* 실행 결과
        sumTest1 : 30
        sumTest2 : 50
        sumTest : 70
     */
}

 

Class

/*
    Java에서 모든 Class가 Object를 상속받고 있듯이 코틀린은 모른 클래스가 Any 클래스를 상속받고있다.
    객체 생성은 Java와 유사하지만 간결한 표현을 위해 new 키워드가 생략되었다.
 */

// String 객체 생성
var str = String()

/*
    생성자

    생성자를 명시하지 않으면 Java와 같이 Default 생성자를 가진다.
    클래스 선언시 Calc() 로 선언할수 있다. () 는 생략가능하다.
 */
/**
 * 생성자를 명시하지 않으면 Java와 같이 Default 생성자를 가진다.
 * 클래스 선언시 Calc() 로 선언할수 있다. () 는 생략가능하다.
 */
class Calc {
    fun sum(a: Int, b: Int): Int {
        return a + b
    }
}


/**
 * Default constructor 를 가진 Class 정의
 * Cal1 뒤에 괄호는 생략 해도 됨
 */
class Calc1() {
    // init block 은 Class 가 생성 될때 실행 된다.
    init {
        println("Class 가 생성 될때 실행 된다.")
    }

    fun sum(a: Int, b: Int): Int {
        return a + b
    }
}


/**
 * Argument가 있는 constructor를 가진 Class 정의
 */
class SmartPhone(manufacturer: String, model: String) {
    init {
        println("제조사는 : ${manufacturer}, 모델명은 : ${model}")
    }
}

fun testArgumentClass() {
    var phone = SmartPhone("SAMSUNG", "Note 20 Ultra")
    // 출력 : 제조사는 : SAMSUNG, 모델명은 : Note 20 Ultra
}


/**
 * 생성자를 Private으로 선언
 * 외부에서 객체 생성을 할수 없게 막음
 */
class PrivateConstructClass private constructor() {
    init {
        println("Private construct class..")
    }

    /**
     * companion object 는 Java의 static 과 유사하다.
     * companion object 블럭에 정의된 함수는 java의 static 함수와 동일하게 접근 할 수 있다.
     * 단 하나의 Class에 companion object 는 하나만 선언할 수 있다고 한다.
     */
    companion object { // companion object 는 java 의 static 이라고 생각해도 된다.
        fun create(): PrivateConstructClass {
            return PrivateConstructClass()
        }
    }
}

fun testPrivateConstructClass() {
    var privateConstructClass = PrivateConstructClass.create()

}

/**
 * Companion object 는 클래스 하나에 하나만 선언할 수 있다.
 * Companion object 명을 생략해도 된다.
 * companion object 블럭에 정의된 변수, 함수는 java 의 static 과 유사하게 클래스명으로 바로 접근 할 수있다.
 */
class CompanionObjectClass {
    companion object Calc { //Companion obj
        val value1 = "SUM"
        val value2 = "TEST"

        fun sum(a: Int, b: Int): Int {
            return a + b
        }
    }
}

class CompanionObjectClass1 {
    companion object { // companion object 명을 생략 할 수 있다.
        val value1 = "SUM"
        val value2 = "TEST"

        fun sum(a: Int, b: Int): Int {
            return a + b
        }
    }
}

fun testCompanionObjectClass() {
    println("Companion object 를 통해 접근 할수 있다: ${CompanionObjectClass.Calc.sum(1, 4)}")
    println("Companion object 를 통해 접근 할수 있다: ${CompanionObjectClass.Calc.value1}")
    println("Companion object 를 통해 접근 할수 있다: ${CompanionObjectClass.Calc.value2}")
    println("Class로 바로 Companion object에 접근 할수 있다: ${CompanionObjectClass.sum(1, 4)}")
    println("Class로 바로 Companion object에 접근 할수 있다: ${CompanionObjectClass.value1}")
    println("Class로 바로 Companion object에 접근 할수 있다: ${CompanionObjectClass.value2}")
    println("Companion object 명을 생략 할 수도 있다: ${CompanionObjectClass1.sum(2, 3)}")
}

class ConstructorOverloading {
    val title:String
    val subject:String
    val count:Int

    constructor(title:String, subject:String, count:Int){
        this.title = title;
        this.subject = subject;
        this.count = count;
    }

    constructor(title: String, subject: String) : this(title, subject, 0)

    constructor(title:String) : this(title, title){
        // 추가적인.. 무언가를 할 수 있다.
    }

    fun print(){
        println("Title은 ${title}, Subject는 ${subject}, Count는 ${count}이다.")
    }
}
fun testConstructorOverloading(){
    ConstructorOverloading("Kotlin").print()
    ConstructorOverloading("Kotlin", "공부하기").print()
    ConstructorOverloading("Kotlin", "공부하기", 7).print()
    /*
        Title은 Kotlin, Subject는 Kotlin, Count는 0이다.
        Title은 Kotlin, Subject는 공부하기, Count는 0이다.
        Title은 Kotlin, Subject는 공부하기, Count는 7이다.
     */
}


fun main(args: Array<String>) {
    println("Default 생성자 (괄호 생략) : ${Calc().sum(10, 30)}")
    println("Default 생성자 (괄호) 첫번째 : ${Calc1().sum(10, 30)}")
    println("Default 생성자 (괄호) 두번째 : ${Calc1().sum(10, 30)}")
    testArgumentClass()
    testPrivateConstructClass()
    testCompanionObjectClass()
    testConstructorOverloading()
}