Kotlin을 시작해보자. (Lambda, Class)
Kotlin2020. 9. 9. 22:24
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()
}