inflearn logo
강의

講義

知識共有

Java開発者向けのコトリン入門(Java to Kotlin Starter Guide)

20講. Kotlinのスコープ関数

[20강] run 질문

261

RealTake

投稿した質問数 11

1

run은 아래와 같이 T에 대한 확장 함수를 받는데

public inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}

personReopository의 save를 메서드 레퍼런스로 호출할 때 person 객체 즉 this 를 넘겨야하는데,

위의 run의 구현부를 봤을 때 는 파라미터로 아무 것 도 넘겨 주지 않고 어떻게 this를 받아서 아래 와같이 사용이 될수있는지 궁금합니다.

val person= Person(name: "최태현", age: 100).run(personRepository::save)

java kotlin 객체지향

回答 2

0

RealTake

답변 감사 드립니다 ㅠ

진짜 마지막으로궁금한게 있습니다

 

아래 예제로 주신 코드는 실제로 가능한 문법일까요 ?

실제로 해보려는데 안돼서 ,,

val f = Pereson.function() {
  personRepository.save(this)
}

강의에서는 비슷한 문법을 못본것 같아서요ㅜ.

 

아래 처럼은 되는것 같은데ㅜ

위 코드는 단지 이해하기 편하도록 작성해주신건지 궁금합니다

 

 val f:Person.() -> Unit= {
       println(this)
    }

 

0

lannstark

아이고 편하게 계속해서 질문 주셔도 괜찮습니다 ㅎㅎㅎ 👍

이해를 돕기 위해 대략 작성한 코드에요!! 컴파일 안되는게 맞을겁니다!

 

대신 이런식으로는 가능합니다!

val f = fun String.(num: Int) { // String이 확장함수의 수신객체 타입이 됩니다!

}

 

작성해주신 방식으로도 가능한데, 작성해주신 방식은 "람다식"을 사용한 방식, 제가 위에 작성한 방식은 fun 키워드를 사용한 방식으로 봐주시면 될 것 같아요!

감사합니다!! 😊 🙏

0

lannstark

안녕하세요 RealTake님! 🙂 질문 남겨주셔서 감사합니다!

 

질문주신 내용이 두 가지로 해석되어 각각 설명드려보겠습니다.

 

[1. 메소드 레퍼런스 측면]

  • personRepository::Save 라는 메소드 레퍼런스를 사용했을 때

  • 우리가 personRepository.save(person) 처럼 person 이라는 매개변수를 넘기지 않았는데

  • 어떻게 personsave 메소드로 넘어갈 수 있는가!

     

이 기능은 코틀린의 기능이라기 보다는 자바와 코틀린에 동일하게 존재하는 메소드 레퍼런스의 특징입니다!

예를 들어 자바에서도

list.forEach(System.out::println);

이런 코드를 한 번쯤 보셨을 거에요! forEach 를 이용해 list 안에 있는 원소들을 System.out.println(원소) 로 넘겨주는 코드죠!

비슷하게 person 자체가 personRepository.save(person) 의 매개변수로 자연스럽게 들어갔다고 생각할 수 있습니다!

 

[2. run(block: T.() -> R) 측면]

  • run 의 매개변수 block은 T.() -> R 로 매개변수가 존재하지 않습니다! ()

  • 그런데 지금 Person(name: "최태현", age: 100).run(personRepository::save) 이라는 코드는 personRepository.save(person) 처럼 person을 매개변수로 넘기고 있죠!

  • 이게 어떻게 가능한 것인가!

 

이 경우는 Person(name: "최태현", age: 100).run(personRepository::save) 코드를 다음과 같이 단계별로 해석해볼 수 있습니다! 각 단계는 동일한데요, run(personRepository::save) 부분만 떼어서 보도록 하겠습니다.

 

  • run(personRepository::save)

  • run { personRepository.save(this) } <- 이때 this가 pereson 인스턴스가 됩니다.

val f = Pereson.function() {
  personRepository.save(this)
}
Person().run(f)

이 때 잘 보면 우리가 만든 익명 함수 Person.function() 은 매개변수가 없습니다! 단지 매개변수가 없는 그 함수 안에서 personRepository::save 를 호출할 때 this 를 넘겨주고 있는거죠!

아마 마지막 단계로 코드가 분해될 수 있는 것을 이해하시면, 갖고 계신 의문이 쉽게 해결될 수 있을 것 같습니다!! 👍

 

답변이 도움이 되었으면 좋겠습니다. 추가적인 질문 있으시면 언제든 편하게 남겨주세요~!!

감사합니다! 🙏

0

RealTake

답변 감사드립니다!

제가 자바만 써와서 그런지
아직 이해가 안되는건 this를 넘겨줄 생각을 자동으로 한게 신기합니다..

자바는 아래 처럼 인터페이스 accept를 사용해서 t라는 이미 넘겨줄 파라미터를 정의 하고있어서 메소드레퍼런스로 넘겨줄 println에 파라미터로 줄 수 있다고 생각이드는데

@FunctionalInterface
public interface Consumer<T> {
  void accept(T t);
}

Consumer<String> func = System.out::println;
func.accept("Hello");

 

코틀린은 그런거 없이 줄 수 있는 가장 적절한 파라미터로 똑똑하게 알아서 this를 넘겨준걸까요?

val f = Pereson.function() {
  personRepository.save(this)
}
Person().run(f)

0

lannstark

안녕하세요! RealTake님! 🙂

 

먼저 this 자체는 코틀린의 확장함수와 관련되어 있다는 것을 잘 알고 계실 것 같습니다!

예를 들어 아래 함수를 보면, 단순히 function으로 시작하는게 아니라 Person.function 즉, Person 객체의 확장 함수로 동작하는 것을 알 수 있죠!

val f = Pereson.function() {
  personRepository.save(this)
}

확장 함수를 사용하게 되면, 내부적으로 this 를 사용했을 때 확장 함수의 수신 객체 (여기서는 Person 타입의 인스턴스가 됩니다)를 받을 수 있죠!

 

사실 이러한 확장함수는 ByteCode로 만들어 Decompile을 해보면, static 함수 + 첫 번째 매개변수를 Person으로(= 수신객체로) 갖고 있습니다. 예를 들어 위의 코드가 컴파일 되면,

public static void anonymousFunction(Person p) {
  personRepository.save(p);
}

로 변경됩니다.

 

그리고 이제 다음 코드를 생각해보면,

Person().run(personRepository::save)

결국 컴파일 되었을 때 익숙하신 것처럼, "이미 넘겨줄 파라미터를 정의하고 있는 함수를 호출"하는 것과 같다고 생각할 수 있어요! 확장함수를 사용한다는 것은 사실, 수신객체 타입을 매개변수로 받는 static 함수를 사용하는 것과 같기 때문이죠.

 

결론적으로, 겉보기에는 똑똑하게 this를 넘겨준 것처럼 보이고, 실제 컴파일을 하면, 매개변수가 있는 함수 형태로 바뀌기 때문에 기존 자바와 크게 동작이 다르지 않다 라고 이해해주시면 될 것 같습니다.

답변이 도움이 되었으면 좋겠습니다. 감사합니다! 🙏

수업노트

0

52

1

싱글톤과 스프링

0

71

2

get() = 3

0

49

2

강사님

0

74

1

강의 복습하면서 생긴 질문

1

93

1

Kotlin과 Java의 현업에서의 활용

0

121

2

data class와 자바의 Lombok을 이용한 DTO 클래스 차이 질문

0

72

1

코틀린에서 상속 시, 주의점에 대한 질문

1

95

3

내용 이해 질문

0

56

1

자바와 코틀린의 함수형 프로그래밍,

1

91

1

플랫폼 타입 설명 문의

2

73

2

널 아님 단언 관련 질문

0

83

1

강의 중 질문

0

79

2

범위 비교 질문

1

91

2

타입캐스팅 궁금한점 질문드립니다.

1

239

2

코틀린 val 질문

0

166

2

완강 후 Kotlin 이런저런 질문 드려봅니다!

3

408

2

확장함수 스타일 질문

0

138

2

확장 프로퍼티 질문

1

156

1

update 함수를 만든다는게 어떤 의미인지 예시가 궁금합니다!

1

283

1

java class의 NotNull 어노테이션 인식

1

260

1

[16강] 확장함수 관련 질문입니다!

1

130

2

리턴타입 사용시 any를 사용해도 괜찮은가요?

1

138

1

안녕하세요 scope function 에 receiver 가 없는 경우

1

168

1