- Gurgen Gevondov์ ๊ธ์ ์ฝ๊ณ ์ ๋ฆฌํ ์ํฐํด์ ๋๋ค.
- ๊ณ ์ฐจํจ์: ๋ค๋ฅธ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๊ฑฐ๋ ํจ์๋ฅผ ๋ฐํํ๋ ํจ์
- ๋๋ค์์ ํจ์ํ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ํด๋์ค๋ก ์ปดํ์ผ ๋๋ค.
- Callable references: ์์ฑ์, ํจ์, ํ๋กํผํฐ์ ์ฐธ์กฐ๊ฐ(::)์ ํจ์ ํ์ ์ผ๋ก ๋ณํ๋ ์ ์๋ค(๋ชจ๋ KCallable์ ๊ณตํต ์กฐ์์ผ๋ก ๊ฐ๊ณ ์๋ค)
- Bounded Member Reference: ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ๋จ ํ๋๋ง ํธ์ถํ๋ ํจ์ ๊ฐ(๋ ํผ๋ฐ์ค)๋ฅผ ๋ง๋ค์ด์ค๋ค.
์ถํ, ํด๋น ๋ด์ฉ๋ค์ ์๊ธฐ ์ฝ๊ฒ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค! ๐ช
๋๋ ๊ณ ์ฐจํจ์๋ฅผ ๋๊ธธ ๋ ๋ฉค๋ฒ ์ฐธ์กฐ์ ::
์ ๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก ์ ์ฉํ๋ค.
1) ๋๋ค์์ ๋นํด ๊ฐ๋
์ฑ์ด ์ข๋ค.
2) ๋๋ค์์ ๊ฐ์ฒด ์์ฑ ๋น์ฉ์ ์ค์ผ ์ ์๋ค.
student.maxBy { it.age }
student.maxBy(Student::age) // ๋ ์ดํดํ๊ธฐ ์ฝ๋ค!
๊ทธ๋ฌ๋, ๋ ์๊ฐ ์ถ์ฒํด์ฃผ์ ๋ธ๋ก๊ทธ ๊ธ์ ์ฝ๊ณ , ::
์ ์ ๋ชจ๋ฅด๊ณ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ๊นจ๋ฌ์๋ค. ๐ฅฒ
๊ทธ๋ผ Quiz๋ฅผ ํตํด ๋
์๋ค์ ::
์ ๋๋ค์ ์ฐจ์ด๋ฅผ ์ ์๊ณ ์๋์ง ํ์ธํด๋ณด์~
::
์ ๋๋ค ์ฐจ์ด ์ ์๊ณ ์๋? ๐คprivate class ButtonClickListener {
fun onClick() {
println("Button clicked")
}
}
๋ฒํผ์ ๋๋ ์ ๋์ Action์ ๋ํ๋ด๋ ButtonClickListener ๊ฐ ์๋ค.
private class Button(
private val listener: ClickListener
) {
fun performClick() = listener.onClick()
}
ํด๋น listener๋ Button ์ ๋ฉค๋ฒ์ด๊ณ , performClick() ์ ํธ์ถ ์ listener ์ ์ด๋ฒคํธ๊ฐ ์ํ๋๋ค.
private class ScreenView {
lateinit var listener: ClickListener
val button = Button(listener::onClick)}
val button2 = Button { listener.onClick()
}
ScreenView ๋ listener, button ๊ณผ button2 ๋ฅผ ๋ฉค๋ฒ๋ก ๊ฐ์ง๊ณ ์๋ค.
๋๋ค์
์ผ๋ก ์ด๋ฒคํธ๋ฅผ ์ ๋ฌ๋ฐ๋๋ค.ํ๋กํผํฐ ๋ ํผ๋ฐ์ค
๋ก ์ด๋ฒคํธ๋ฅผ ์ ๋ฌ๋ฐ๋๋ค.fun main() {
ScreenView().apply {
listener = ButtonClickListener() // listener ์ด๊ธฐํ
button.performClick()
button2.performClick()
}
}
ํด๋น main()
๋ฅผ ํธ์ถํ๋ฉด ๊ฒฐ๊ณผ๊ฐ ์ด๋ป๊ฒ ๋์ฌ๊น?!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
๋๋ฅ! ํ๋ก๊ทธ๋๋ฐ์ด ์ฃฝ๋๋ค! ๐.
๐คฏ Error ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ listener ๊ฐ ์์ง ์ด๊ธฐํ๋์ง ์์๋๋ฐ listener๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํฌ๋์ฌ๊ฐ ๋ฌ๋ค๊ณ ํ๋ค
์ฐ๋ฆฌ๋ ๋ถ๋ช
main() ํจ์์์ ScreenView์ listener๋ฅผ ์ด๊ธฐํํด์ฃผ์๋ค.
๊ทธ๋ฐ๋ฐ ์ ์ด๊ธฐํ ์๋ฌ๋ก ํ๋ก๊ทธ๋จ์ด ํฐ์ง๊น?!
์ด์ ๋ฅผ ์๊ธฐ ์ํด์ java ์ฝ๋๋ก ๋์ปดํ์ผ ํด๋ณด์ ๐ช
์ด๋์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฑด์ง ๊ณ ๋ฏผํด๋ณธ ํ ์ฝ์ด๋ณด๋๊ฑธ ์ถ์ฒํ๋ค.
private class ScreenView {
lateinit var listener: ClickListener
val button = Button(listener::onClick)
...
ํด๋น ScreenView ๋ฅผ ๋์ปดํ์ผํด๋ณด๋ฉด button์ ScreenView ์ ์์ฑ์์์ ์ด๊ธฐํํ๊ณ ์๋ค.
public ScreenView() {
Button var10001 = new Button;
Function0 var10003 = new Function0() {
...
public final void invoke() {
((ButtonClickListener)this.receiver).onClick();
}
};
ButtonClickListener var10005 = this.listener;
if (var10005 == null) {
Intrinsics.throwUninitializedPropertyAccessException("listener");
}
var10003.<init>(var10005); // listener::onClick ํ ๋น
var10001.<init>((Function0)var10003); // Button ํ ๋น
this.button = var10001;
...
์์ฒญ ๋ณต์กํด๋ณด์ธ๋ค..
์ฐจ๊ทผ์ฐจ๊ทผ ๋ฏ์ด๋ณด์! ๐ช
var10003
๋ถ๋ถFunction0 var10003 = new Function0() {
...
public final void invoke() {
((ButtonClickListener)this.receiver).onClick();
}
};
Function0 ์ต๋ช
class์ ์ธ์คํด์ค๋ฅผ var1003
๋ณ์์ ํ ๋นํ๊ณ ์๋ค.
๊ทธ ์ด์ ๋, listener::onClick
์ ๋๋ค์์ผ๋ก ๋ณํํ์ฌ Button์ ์์ฑ์๋ก ๋๊ธฐ๊ธฐ ์ํจ์ด๋ค.
๋๋ค์์ FunctionN ์ธํ ํผ์์ค๋ฅผ ๊ตฌํํ๋ ์ต๋ช class์ ์ธ์คํด์ค๋ค.
Function0 ์ต๋ช
class์ invoke()
๋ด๋ถ์ this.receiver
๋ฅผ ๋ณผ ์ ์๋๋ฐ, receiver
๊ฐ ๋ฐ๋ก listener::onClick
์ ์์ ๊ฐ์ฒด listener
๋ค.
์ฆ, invoke() ๊ฐ ํธ์ถ๋ ๋ listener.onClick()
์ด ์คํ๋๋ค.
lateinit var listener: ClickListener // ์๊ฐ this.receiver ๋ฅผ ๋ปํจ
์ ๋ฆฌ)
1) listener::onClick
๋ฅผ Function0 ์ต๋ช
class ๋ก wrappingํ์ฌ ๋๋ค์์ผ๋ก ๋ง๋ค๊ณ ์์
2) button์ performClick() ์ด ํธ์ถ๋ ๋๋ง๋ค ์์ invoke()
ํจ์๊ฐ ํธ์ถ๋ ๊ฒ์
var10005
๋ถ๋ถ ์ฝ๋ ํด์ButtonClickListener var10005 = this.listener;
if (var10005 == null) {
Intrinsics.throwUninitializedPropertyAccessException("listener");
}
listener๋ฅผ var1005
๋ณ์์ ํ ๋นํ๊ณ ์๊ณ , var1005
๊ฐ ์ด๊ธฐํ๋์ง ์์์ผ๋ฉด Exception์ ๋์ง๋ค๊ณ ํ๋ค.
ScreenView๊ฐ ์ด๊ธฐํ๋ ๋, listener๊ฐ ์์ง ์์ง ์ด๊ธฐํ๋์ง ์์๋ค.
๋ฐ๋ผ์, ์ null ๊ฒ์ฆ๋ฌธ์ ํต๊ณผํ์ง ๋ชปํด UninitializedPropertyAccessException์ด ๋ฐ์ ๐ฑ
// ScreenView๊ฐ ์ด๊ธฐํ๋ ๋ null ๊ฒ์ฌํจ, ๊ทผ๋ฐ ์์ง ์ด๊ธฐํ ์๋์ผ๋ ํ! ๐ป
ScreenView().apply {
listener = ButtonClickListener() // listener ์ด๊ธฐํ
button.performClick()
button2.performClick()
}
๊ทธ๋ผ ์ด์ ๋๋ค์์ ํตํด ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ button2์ ๋์ปดํ์ผ๋ ์ฝ๋๋ฅผ ๋ถ์ํด๋ณด์~
class ScreenView{
val button2 = Button { listener.onClick() }
...
// java
private static final class ScreenView {
private final Button button2 = new Button((Function0)(new Function0() {
public final void invoke() {
ScreenView.this.getListener().onClick();
}
}));
...
button์ ๋ฌ๋ฆฌ button2๋ listener์ ์ด๊ธฐํ ๊ฒ์ฌ๋ฅผ ScreenView๊ฐ ์์ฑ๋ ๋ ํ์ง ์๋๋ค.
@NotNull
public final ButtonClickListener getListener() {
ButtonClickListener var10000 = this.listener;
if (var10000 == null) {
Intrinsics.throwUninitializedPropertyAccessException("listener");
}
return var10000;
}
button2 ๋ this.getListener()
๋ฅผ ํธ์ถ๋ ๋ ์ด๊ธฐํ ๊ฒ์ฌ๋ฅผ ํ๊ณ ์๋ค.
buttone2.performClick() // ์ด ๋ listener๊ฐ ์ด๊ธฐํ๋๋์ง ๊ฒ์ฌ
์ฆ, buttone2.performClick()
์ด ํธ์ถ๋ ๋ ๋๋ค์ invoke() ํจ์์์ ์ด๊ธฐํ ๊ฒ์ฌ๋ฅผ ํ๊ธฐ ๋๋ฌธ์, ScreenView๋ฅผ ์์ฑํ ๋
๋ฐ๋ผ์, ๋๋ค๋ฅผ ํ์ฉํด ๊ณ ์ฐจํจ์๋ฅผ ๋๊ธธ ๋๋ throwUninitializedPropertyAccessException
๊ฐ ๋ฐ์ํ์ง ์๋๋ค. ๐
์ฌ์ค bounded member reference
์ ๋ํ ๊ฐ๋
์ ์ ์๊ณ ์์ผ๋ฉด, ๊ตณ์ด ๋์ปดํ์ผํ์ง ์์๋ ํ๋ก๊ทธ๋จ์ด ํฐ์ง๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
์ ์ด์ bounded member reference
์์ฒด๊ฐ ๋ฉค๋ฒ ์ฐธ์กฐ๋ฅผ ์์ฑํ ๋, ์ธ์คํด์ค๋ฅผ ํจ๊ป ์ ์ฅํ ๋ค์ ๋์ค์ ๊ทธ ์ธ์คํด์ค์ ๋ํด ๋ฉค๋ฒ๋ฅผ ํธ์ถํด์ฃผ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋, ์์ ์์์ ๊ฒฝ์ฐ Listener
๊ฐ ์ด๊ธฐํ๋์ง ์์๋๋ฐ, ํธ์ถํ๋ ๋น์ฐํ ํฐ์ง ์ ๋ฐ์...
lateinit var listener: ButtonClickListener
val onClick = ButtonClickListener::onClick // KFunction1<ButtonClickListener, Unit>
val button = Button { onClick(listener) }
val button2 = Button(listener::onClick) // ์์ ๋๊ฐ๋ค
class Button(
private val onClick: () -> Unit
) {
fun performClick() = onClick()
}
class ButtonClickListener(
private val name: String
) {
fun onClick() {
print(name)
}
}
class ScreenView {
var listener = ButtonClickListener("First")
val buttonLambda = Button { listener.onClick() }
val buttonReference = Button(listener::onClick)
}
fun main() {
val screenView = ScreenView()
screenView.listener = ButtonClickListener("Second")
screenView.buttonLambda.performClick()
screenView.buttonReference.performClick()
}
ํ์ด๋ณด์ญ์ ~!!
์ ๋ต์ SecondFirst
์
๋๋ค. ํฌํฌ
Thanks To Gurgen Gevondov
https://kt.academy/article/fk-function-references
https://proandroiddev.com/kotlin-lambda-vs-method-reference-fdbd175f6845