1. 여러 인스턴스 리턴
: 두 개 이상의 데이터를 포함하는 데이터클래스를 만들고 인스턴스 리턴하기
//메소드는 기본적으로 하나의 데이터를 리턴함
1) Pair = 2개의 인스턴스 리턴
var chicken = Chicken()
var eggs = chicken.getEggs()
var listEggs = eggs.toList()
// 리스트로 관리
var firstEgg = listEggs[0] // = eggs.first
var secondEgg = listEggs[1] // = eggs.second
println("달걀의 종류는 ${eggs} 입니다.") //(달걀, 맥반석) // Pair
println("리스트 달걀의 종류는 ${listEggs} 입니다.") //[달걀, 맥반석] // toList
println("첫번째 달걀의 종류는 ${firstEgg} 입니다.")
println("두번째 달걀의 종류는 ${secondEgg} 입니다.")
}
class Chicken {
fun getEggs(): Pair<String, String> {
var eggs = Pair("달걀", "맥반석")
return eggs
}
}
2) Triple = 3개의 인스턴스 리턴
fun main() {
var chicken = Chicken()
var eggs = chicken.getThreeEggs()
var listEggs = eggs.toList()
// 리스트로 관리
var firstEgg = listEggs[0] // = eggs.first
var secondEgg = listEggs[1] // = eggs.second
var eggTime = listEggs[2] // = eggs.third
println("달걀의 정보는 ${eggs} 입니다.") //(달걀, 맥반석, 20230101)
println("리스트 달걀의 정보는 ${listEggs} 입니다.") //[달걀, 맥반석, 20230101]
println("첫번째 달걀의 종류는 ${firstEgg} 입니다.")
println("두번째 달걀의 종류는 ${secondEgg} 입니다.")
println("달걀은 ${eggTime}에 나왔습니다.")
}
class Chicken {
fun getTwoEggs(): Pair<String, String> {
var eggs = Pair("달걀", "맥반석")
return eggs
}
fun getThreeEggs(): Triple<String, String, Int> {
var eggs = Triple("달걀", "맥반석", 20230101)
return eggs
}
}
2. 자신의 객체 전달
: Scope Functions들을 제공, 객체를 사용할 때 임시로 Scope를 만들어 편리한 코드 작성을 도움
vv 다시 이해하기... @@@@
(1) 명시적으로 수신객체 자체를 람다의 수신객체로 전달하는 방법
public inline fun <T, R> T.run(block: T.() -> R): R
public inline fun <T> T.apply(block: T.() -> Unit): T
public inline fun <T, R> with(receiver: T, block: T.() -> R): R
(2) 수신객체를 람다의 파라미터로 전달하는 방법
public inline fun <T> T.also(block: (T) -> Unit): T
public inline fun <T, R> T.let(block: (T) -> R): R
// T = 수신객체. it으로 사용 가능 but 문제점 있음
// block: 내부는 람다함수의 소스코드
// 모든 수신객체를 it으로 활용할 경우의 문제점 = 제대로 참조하지 못할 수 있음
--> it을 다른 이름으로 변경해 사용하기도 함
// Scope Function을 중첩으로 사용할 경우 누가 누구의 범위인지 알수 없다!
// Implicit parameter 'it' of enclosing lambda is shadowed 경고 발생!
data class Person(
var name: String = "",
var age: Int? = null,
var child: Person? = null
)
// 잘못된 예시
Person().also {
it.name = "한석봉"
it.age = 40
val child = Person().also { //it 안에서 또 also를 한 것
it.name = "홍길동" // 누구의 it인지 모른다!
it.age = 10 // 누구의 it인지 모른다!
}
it.child = child
}
// 수정한 예시
Person().also {
it.name = "한석봉"
it.age = 40
val child = Person().also { c -> //it 이 아니라 c로 넘겨줌!
c.name = "홍길동"
c.age = 10
}
it.child = child
}
- let, with, also, apply, run
it | this | |
{ } 블록 수행 결과를 리턴 | let | run, with |
객체 자신을 반환 | also | apply |
1) let function
: { } 안에 it으로 자신의 객체를 전달, 수행 결과를 반환
var strNum = "10"
var result = strNum?.let { //strNum이 null이 아닐 때
Integer.parseInt(it) //{ } 안에서 strNum을 it으로 대체해 사용 가능
} //parseInt에 strNum을 넘겼을 때 문자열을 숫자로 바꿔 result에 저장
println(result!!+1) //result가 0이 아님을 보장하고 1을 더해 11이 나옴
2) with function
: { } 안에 this로 자신의 객체를 전달, 코드 수행
//this는 생략 가능.
//null이 확실히 아닐 때만 사용하는 것을 권장. this는 언제든 사용 가능하니까
var alphabets = "abcd" //뭔가 들어있으니 null이 아닌 게 확실함
with(alphabets) { //이 뒤부터 { } 안에서 alphabets는 this로 불린다
// var result = this.subSequence(0,2) //this 생략가능
var result = subSequence(0,2)
println(result)
}
3) also function
: { } 안에 it으로 자신의 객체를 전달, 객체 반환
//apply와 자주 사용
fun main() {
var student = Student("참새", 10)
var result = student?.also { //student 객체가 null이 아닐때만 실행
it.age = 50 //student.age 와 동일, age가 바뀐 student 객체가 result에 대입됨.
}
result?.displayInfo() //동일한 결과 나옴
student.displayInfo() //동일한 결과 나옴
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("이름은 ${name} 입니다")
println("나이는 ${age} 입니다")
}
}
4) apply function
: { } 안에 this로 자신의 객체 전달, 객체를 반환
- 객체의 상태 변화시킨 뒤 바로 저장하고 싶을 때 사용
fun main() {
var student = Student("참새", 10)
var result = student?.apply { //여기!!
student.age = 50 //it이 아니라 this로 들어옴, 객체의 상태를 변환하고 바로 반환, result에 대입
}
result?.displayInfo()
student.displayInfo()
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("이름은 ${name} 입니다")
println("나이는 ${age} 입니다")
}
}
5) run function
(1) 객체에서 호출하지 않는 경우
var totalPrice = run { //여기! 임시영역 사용st
var computer = 10000
var mouse = 5000
computer+mouse //totalPrice에 대입됨
}
println("총 가격은 ${totalPrice}입니다")
(2) 객체에서 호출하는 경우 // null이 보장되어야 하는 with와 달리 null 체크 가능, 안전
fun main() {
var student = Student("참새", 10)
student?.run { //여기!! student가 null이 아닐 때만 run 할 수 있음
displayInfo() // = student.displayInfo( ) // = with에서도 this 생략하고 메소드 바로 썼음
}
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("이름은 ${name} 입니다")
println("나이는 ${age} 입니다")
}
}
'언어 > Kotlin' 카테고리의 다른 글
[Kotlin 문법 종합] - 쓰레드, 코루틴 (# 추가하기) (0) | 2024.03.06 |
---|---|
[Kotlin 문법 종합] - 확장함수, 비동기 프로그래밍 @@@수정하기 (2) | 2024.03.06 |
[Kotlin 문법 종합] - 자료형 변환, 타입확인 @@@ 수정하기 (0) | 2024.03.06 |
[Kotlin 문법 종합] - Single-expression function, 싱글턴 (@@질문하기) (1) | 2024.03.06 |
[Kotlin 문법 종합] - 널 세이프티 @@수정하기 (0) | 2024.03.06 |