72일차(1)/Android App(17) : Kotlin에서 java 클래스 사용, Lambda 표현식
- 기존 코틀린 패키지에 우클릭해서 새 패키지 생성
com.example.kotlin_test.java
새 자바 클래스
Member
package com.example.kotlin_test.java;
public class Member {
public int num;
public String name;
public String addr;
public void showInfo(){
System.out.println(num+"|"+name+"|"+addr);
}
}
- 3개의 공개된 필드와 메소드 1개로 작성
- 이 자바 클래스를 코틀린에서 사용 가능할까?
package com.example.kotlin_test
import com.example.kotlin_test.java.MemberDto
fun main(){
//kotlin에서 java 클래스도 자유롭게 import해서 사용할 수 있다.
val mem1=com.example.kotlin_test.java.Member()
mem1.num=1
mem1.name="바나나"
mem1.addr="서울"
mem1.showInfo()
val mem2=MemberDto()
//내부적으로 java의 setter 메소드가 호출된다.
mem2.num=2
mem2.name="딸기"
mem2.addr="부산"
//내부적으로 java의 getter 메소드가
val a = mem2.num;
val b = mem2.name;
val c = mem2.addr;
}
- java 패키지에 들어있는 member 를 import!
- 자동으로 import가 위에 들어오지 않으면 직접 입력해주면 된다.
- 객체 생성 방식, 코딩 방식만 좀 다를 뿐 java 클래스도 import해서 쓸수있다.
MemberDto 생성
package com.example.kotlin_test.java;
public class MemberDto {
public int num;
public String name;
public String addr;
public MemberDto(){}
public MemberDto(int num, String name, String addr) {
this.num = num;
this.name = name;
this.addr = addr;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
- 위 MemberDto를 코틀린에서 import해서 가져와 보면,
get, set 메소드 대신에 필드를 사용하는 느낌으로 메소드가 바뀌어 있다.
- 필드가 호출되는 것처럼 보이지만 클래스의 setter, getter 메소드를 호출하는 것
- 코틀린에서는 getter, setter 메소드를 이렇게 점을 찍어서 필드명으로 사용한다.
Step09_Lambda
package com.example.kotlin_test
/*
Lambda expression (람다 표현식)
- 익명 함수를 람다라고 한다.
*/
fun main(){
//f1이라는 이름의 함수 만들기
fun f1(){
println("f1 함수 호출됨")
}
//만든 f1() 함수 호출하기
f1()
//이름이 없는 함수를 만들어서 바로 호출
(fun(){
println("익명 함수가 호출됨!")
})()
//이름이 없는 함수를 만들어서 변수에 담기
val f2=fun(){
println("f2함수가 호출됨!")
}
f2()
}
- 마치 자바스크립트 같은 모양이다.
- 메인함수 안에서 또다른 함수를 만들어서 호출하는 것이 가능
- java로 만들면 익명 이너클래스로 만들어서 f1 함수를 만들어놓고 그 객체의 메소드를 호출하는 방식으로 바뀔 것이다.
fun(){}
- 이름이 없는 함수. javascript 의 function(){} 과 같은 것!
- 이름없는 함수를 만들어서 바로 호출할 수도 있다.
- 함수 부분 (빨간색 박스) 뒤에 함수 호출 () 이 붙어있는 것!!
(fun(){
println("익명 함수가 호출됨!")
})()
- 이런 형태로 작성 가능하다
- 코틀린의 작성방식은 매우 유연하다.
Step09_Lambda2
package com.example.kotlin_test
fun main(){
/*
in java => public void a(){}
in kotlin => fun a():Unit{} or fun a(){}
코틀린에서 Unit은 원시 타입이라고 지칭하고 java의 void 와 비슷한 역할을 한다.
*/
fun a():Unit{
println("a 함수 호출됨")
}
a()
val isRun:Boolean=true
var myName:String?=null
myName="바나나"
//함수를 만들어서 변수에 담고 싶다면...
//type 추론이 가능하지만, 명시적으로 type을 표시하자고 한다면 어떻게 해야 할까?
/*
()->Unit은
1. 함수에 전달되는 인자는 없으며
2. 아무값도 리턴하지 않는
3. 함수 타입을 의미한다.
*/
val b:()->Unit=fun(){
println("b 함수 호출됨")
}
b()
//fun() 생략 가능
val c:()->Unit = {
println("c 함수 호출됨")
}
/*
(String)->String
1. String type 인자를 하나 받아서
2. String type 을 리턴해주는
3. 함수 타입
*/
val d:(String)->String = fun(name:String):String{
return "내 이름은 ${name}"
}
//위를 아래와 같이 줄일 수 있다.
val e:(String)->String = { name -> "내이름은 ${name}" }
println(e("바나나"))
}
- 여기는 리턴 타입이 들어가는 자리이다.
- java라면 리턴하는 값이 어떤 것도 없다면 void라고 쓰는데,
코틀린은 void 자리의 용어를 생략하거나 Unit 이라고 쓴다.
- Unit을 원시 타입이라고도 한다.
- 생략해도 되고 :Unit 을 작성해주어도 된다.
- 생략해도 된다면 굳이 Unit 이라는 예약어가 필요한 이유는?
- 함수를 담는 변수(b)의 타입은 뭐라고 적어주어야 할까?
- null이 가능한 타입은 ? 를 넣어주어야 한다. 이것이 없으면 null을 넣지 못한다.
:()->Unit
- 함수의 타입은 이렇게 표시해줄 수 있다. 함수 모양을 타입으로 전달할 수 있다.
- Unit 이라는 타입이 없다면 여기에 표시해줄 수가 없다.
- void 를 쓸 수도 없다(void는 예약어가 아니다). 그렇다고 비워두면 문법 오류가 일어난다.
- Unit은 아무것도 리턴하지 않는다 를 나타내는 예약어로써 사용한다!!
** ()->Unit 은
1. 함수에 전달되는 인자는 없으며
2. 아무 값도 리턴하지 않는
3. 함수 타입을 의미한다.
- 여기서 fun() 은 생략 가능하다.
- 이 함수의 타입은 무엇일까?
- string 타입을 인자로 받고 리턴 타입은 string이다. 하지만 함수타입은 string이 아니다.
val d :(String)->String
- 인자로 String 타입을 받고 String 타입을 리턴하는 함수 타입이다.
val e:(String)->String = { name -> "내이름은 ${name}" }
- 이렇게 작성할 수 있다.
- 매개변수에 전달된 값을 기억해서 안에 사용하겠다는 뜻!
- 이렇게 1줄로 작성하는 것을 기억하기!
- 이런 함수의 모양을 이해하고 작성할 수 있으면 된다.
Step09_Lambda3
package com.example.kotlin_test
//함수 type을 매개변수로 전달받는 함수
fun useFunc(f:()->Unit){
//인자로 전달받은 함수 호출하기
f()
}
//인터페이스 정의하기
interface Drill{
fun hole()
}
fun useDrill(d:Drill){
d.hole()
}
fun main(){
useDrill(object:Drill{
override fun hole() {
println("구멍을 뚫어요!")
}
})
//원래 모양
useFunc(fun(){
println("익명함수 호출됨! 1")
})
//fun() 생략
useFunc({
println("익명함수 호출됨! 2")
})
//위를 좀더 간단히 한 최종 모양
useFunc {
println("익명함수 호출됨! 3")
}
}
- 함수를 매개변수로 받을 수 있다.
- 인자는 전달하지 않아도 되고, 리턴타입은 없는 함수를 사용
- 전달받는 함수의 모양을 강제하고 있다는 데에서 의의가 있다.★★
- 이 함수를 main 함수에서 만들어보려고 하면 이런모양이 나온다.
- 원래는 이런 모양이어야 하는데,
- 좀더 간단하게 작성할 수 있다. 최종적으로 이런모양이 된다.
- useFunc() 이라는 함수를 호출하면서 함수를 전달하는 구조이다.
- 이 안에 들어간 이것 자체가 함수이다!
- 같은 유형의 함수이기 때문에 그래서 useFunc() 안에 인자로 받아질 수 있는것이다.
interface Drill{
fun hole()
}
fun useDrill(d:Drill){
d.hole()
}
- 드릴 인터페이스타입을 전달받아서 hole 메소드를 사용하기!
- 메인 메소드 안에서 전달하려면 object 예약어와 함께 Drill 인터페이스 가져오기
- 익명 클래스를 사용해서 인터페이스의 참조값을 얻어내서 사용!
'국비교육(22-23)' 카테고리의 다른 글
72일차(3)/Android App(19) : View Binding (0) | 2023.01.19 |
---|---|
72일차(2)/Android App(18) : Fragment(2), Fragment Lifecycle (0) | 2023.01.18 |
71일차(2)/Android App(16) : Fragment(1) (1) | 2023.01.18 |
71일차(1)/Android App(15) : Kotlin Abstract Class, Companion, Map (0) | 2023.01.17 |
70일차(2)/Android App(14) : Kotlin Extend, Interface / inner class 사용하기 (0) | 2023.01.16 |