서문
CallBack은 콜백을 의미합니다. Windows 프로그래밍에 익숙한 사람이라면 "콜백 함수"라는 네 단어가 익숙할 것입니다. 그러나 Java 프로그래머는 이에 대해 잘 알지 못할 수도 있습니다. "콜백 함수" 또는 "콜백 방법"은 소프트웨어 설계 및 개발에 있어 매우 중요한 개념입니다. "콜백 함수"에 대한 개념을 익히는 것은 (어떤 언어를 사용하든) 프로그래머에게 매우 필요합니다.
최근 Java를 배우며 콜백 메커니즘(CallBack)을 접하게 되었습니다. 처음 만났을 때 꽤 헷갈린다고 느꼈고, 인터넷에서 찾은 관련 설명이 한 문장으로 설명되어 있거나, 비교적 단순해서 콜백에 대한 정의를 내리는 것 같았습니다. 물론 콜백을 이해한 후 인터넷에 가서 여러 설명을 찾아봤는데 정말 문제가 없었습니다. 하지만 초보자인 저에게는 단계별 프로세스가 누락되어 있습니다. 여기에서는 콜백 메커니즘에 대한 개인적인 이해를 얕은 것부터 깊은 것 순으로 설명하겠습니다. 잘못된 것이 있으면 언제든지 알려주시기 바랍니다.
시작하기 전에 장면을 상상해 보십시오. 유치원 아이들이 방금 10 이내의 덧셈을 배웠습니다.
1장. 이야기의 유래
유치원 선생님이 칠판에 방정식 "1 + 1 = "을 썼고, 샤오밍이 빈칸을 채웠습니다.
10 이내의 덧셈을 배웠기 때문에 Xiao Ming은 이 문제를 혼자서 완전히 계산할 수 있습니다.
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } private int calcADD(int a, int b) { return a + b; } public void fillBlank(int a, int b) { int result = calcADD(a, b); System.out.println(name + "心算:" + a + " + " + b + " = " + result); } }
Xiao Ming 학생들은 빈칸을 채울 때(fillBalnk) 암산(clacADD)을 하여 결과가 2라는 것을 알고 빈칸에 그 결과를 적었습니다. 테스트 코드는 다음과 같습니다.
public class Test { public static void main(String[] args) { int a = ; int b = ; Student s = new Student("小明"); s.fillBlank(a, b); } }
실행 결과는 다음과 같습니다.
샤오밍의 암산: 1 + 1 = 2
프로세스 완료 Student 클래스의 인스턴스 객체만으로 완료되며 콜백 메커니즘은 포함되지 않습니다.
2장. 유치원 선생님의 고민 찾기
쉬는 시간에 유치원 선생님은 문득 생각이 나서 칠판에 샤오밍에게 “168 + 291 =”이라고 써 주었습니다. 마치고 사무실로 돌아왔습니다.
꽃 문지르기! 왜 모든 선생님들은 샤오밍 때문에 어려움을 겪나요? 분명히 최고 수준입니다. 알았습니다! 이때 Xiao Ming은 위와 같은 암산에 더 이상 의존할 수 없음이 분명했습니다. 그가 혼란스러워했을 때, 같은 반 친구인 Xiao Hong은 덧셈만 계산할 수 있는 계산기를 건네주었습니다(수익자)! ! ! ! Xiao Ming은 우연히 계산기 사용법을 알고 있었기 때문에 계산기를 사용하여 결과를 계산하고 빈칸을 채웠습니다.
계산기 코드는
public class Calculator { public int add(int a, int b) { return a + b; } }
Student 클래스를 수정하고 계산기 사용 방법을 추가합니다.
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } @SuppressWarnings("unused") private int calcADD(int a, int b) { return a + b; } private int useCalculator(int a, int b) { return new Calculator().add(a, b); } public void fillBlank(int a, int b) { int result = useCalculator(a, b); System.out.println(name + "使用计算器:" + a + " + " + b + " = " + result); } }
테스트 코드는 다음과 같습니다.
public class Test { public static void main(String[] args) { int a = ; int b = ; Student s = new Student("小明"); s.fillBlank(a, b); } }
실행 결과는 다음과 같습니다.
Xiao Ming은 다음을 사용합니다. 계산기: 168 + 291 = 459
콜백 메커니즘은 아직 이 프로세스에 포함되지 않지만 Xiao Ming의 작업 중 일부가 전송되어 계산기의 지원을 받습니다.
3. 유치원 선생님이 돌아와서
Xiao Ming이 세 자리 덧셈을 완료한 것을 발견했습니다. 선생님은 Xiao Ming이 매우 똑똑하고 유연하다고 생각했습니다. 재능. 그래서 그는 칠판에 "26549 + 16487 = "이라고 쓰고 수업에 가기 전에 Xiao Ming에게 빈칸을 채우도록 요청한 후 사무실로 돌아 왔습니다.
샤오밍은 교실 밖에서 친구들이 즐겁게 노는 모습을 보며 안타까움을 금할 수 없었습니다. 우리가 놀러 나가지 않으면 이 쉬는 시간이 망가질 거예요! ! ! ! 샤오홍이 다시 건네준 계산기를 보고 샤오밍은 계획을 떠올렸다. 샤오홍이 그녀에게 계산기를 하게 하는 것이다.
샤오밍은 샤오홍에게 주제가 '26549 + 16487 = '이라고 말했고, 결과를 채울 구체적인 위치를 지적한 뒤 즐겁게 놀러 나갔다.
여기서는 샤오홍을 별도로 구현하는 것이 아니라 덧셈과 샤오홍만 전체적으로 수행할 수 있는 계산기, 결과를 계산하고 빈칸을 채울 수 있는 슈퍼 계산기라고 생각합니다. 이 슈퍼 계산기에 전달해야 하는 매개변수는 두 개의 가수와 채워야 할 위치이며, 이러한 내용은 Xiao Ming에게 미리 알려야 합니다. 이는 Xiao Ming이 자신의 방법 중 일부를 Xiao Hong에게 공개하고 싶어 함을 의미합니다. 가장 간단한 방법은 Xiaohong에게 인용문과 두 덧셈을 함께 알려주는 것입니다.
따라서 슈퍼 계산기의 add 메소드에는 두 개의 피연산자와 Xiao Ming 자신에 대한 참조가 포함되어야 합니다. 코드는 다음과 같습니다.
public class SuperCalculator { public void add(int a, int b, Student xiaoming) { int result = a + b; xiaoming.fillBlank(a, b, result); } }
Xiao Ming 측. 이제 암산을 하거나 계산기를 사용할 필요가 없으므로 Xiaohong에게 도움을 요청하는 방법만 있으면 됩니다. 코드는 다음과 같습니다.
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } public void callHelp (int a, int b) { new SuperCalculator().add(a, b, this); } public void fillBlank(int a, int b, int result) { System.out.println(name + "求助小红计算:" + a + " + " + b + " = " + result); } }
테스트 코드는 다음과 같습니다.
public class Test { public static void main(String[] args) { int a = ; int b = ; Student s = new Student("小明"); s.callHelp(a, b); } }
실행 결과는 다음과 같습니다.
Xiao Ming이 Xiao Hong에게 도움을 요청합니다. 계산: 26549 + 16487 = 43036
실행 프로세스는 다음과 같습니다. Xiao Ming은 자신의 callHelp 메소드를 통해 Xiao Hong의 add 메소드(새로운 SuperCalculator())를 호출합니다.
(this)를 매개변수로 계산기를 사용하여 결과를 얻은 후 Xiao Ming의 fillBlank 메서드를 다시 호출하여 결과를 칠판의 빈 공간에 채웁니다.
빛, 빛, 빛! 이 시점에서 공식적으로 콜백 함수가 등장합니다. Xiao Ming의 fillBlank 메소드는 우리가 흔히 콜백 함수라고 부르는 것입니다.
이런 방식으로 교사의 빈칸 채우기 문제를 완료하는 작업에서 Xiao Ming은 더 이상 추가가 완료되고 결과가 나올 때까지 기다릴 필요가 없음을 분명히 알 수 있습니다. 친구들은 재미있게 놀았고, 슈퍼 계산기 샤오홍은 빈칸을 채우는 일을 해냈습니다. 풀백의 장점은 이미 나타나기 시작했습니다.
4장. 문 앞의 시어머니
幼稚园的门口有一个头发花白的老婆婆,每天风雨无阻在那里摆着地摊卖一些快过期的垃圾食品。由于年纪大了,脑子有些糊涂,经常算不清楚自己挣了多少钱。有一天,她无意间听到了小明跟小伙伴们吹嘘自己如何在小红的帮助下与幼师斗智斗勇。于是,婆婆决定找到小红牌超级计算器来做自己的小帮手,并提供一包卫龙辣条作为报酬。小红经不住诱惑,答应了。
回看一下上一章的代码,我们发现小红牌超级计算器的add方法需要的参数是两个整型变量和一个Student对象,但是老婆婆她不是学生,是个小商贩啊,这里肯定要做修改。这种情况下,我们很自然的会想到继承和多态。如果让小明这个学生和老婆婆这个小商贩从一个父类进行继承,那么我们只需要给小红牌超级计算器传入一个父类的引用就可以啦。
不过,实际使用中,考虑到java的单继承,以及不希望把自身太多东西暴漏给别人,这里使用从接口继承的方式配合内部类来做。
换句话说,小红希望以后继续向班里的小朋友们提供计算服务,同时还能向老婆婆提供算账服务,甚至以后能够拓展其他人的业务,于是她向所有的顾客约定了一个办法,用于统一的处理,也就是自己需要的操作数和做完计算之后应该怎么做。这个统一的方法,小红做成了一个接口,提供给了大家,代码如下:
public interface doJob { public void fillBlank(int a, int b, int result); }
因为灵感来自帮小明填空,因此小红保留了初心,把所有业务都当做填空(fillBlank)来做。
同时,小红修改了自己的计算器,使其可以同时处理不同的实现了doJob接口的人,代码如下:
public class SuperCalculator { public void add(int a, int b, doJob customer) { int result = a + b; customer.fillBlank(a, b, result); } }
小明和老婆婆拿到这个接口之后,只要实现了这个接口,就相当于按照统一的模式告诉小红得到结果之后的处理办法,按照之前说的使用内部类来做,代码如下:
小明的:
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } public class doHomeWork implements doJob { @Override public void fillBlank(int a, int b, int result) { // TODO Auto-generated method stub System.out.println(name + "求助小红计算:" + a + " + " + b + " = " + result); } } public void callHelp (int a, int b) { new SuperCalculator().add(a, b, new doHomeWork()); } }
老婆婆的:
public class Seller { private String name = null; public Seller(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } public class doHomeWork implements doJob { @Override public void fillBlank(int a, int b, int result) { // TODO Auto-generated method stub System.out.println(name + "求助小红算账:" + a + " + " + b + " = " + result + "元"); } } public void callHelp (int a, int b) { new SuperCalculator().add(a, b, new doHomeWork()); } }
测试程序如下:
public class Test { public static void main(String[] args) { int a = ; int b = ; int c = ; int d = ; Student s = new Student("小明"); Seller s = new Seller("老婆婆"); s.callHelp(a, b); s.callHelp(c, d); } }
运行结果如下:
小明求助小红计算:56 + 31 = 87
老婆婆求助小红算账:26497 + 11256 = 37753元
最后的话
可以很明显的看到,小红已经把这件事情当做一个事业来做了,看她给接口命的名字doJob就知道了。
更多详解 JAVA的回调机制CallBack相关文章请关注PHP中文网!