Java엔 delegate가 없다
c#에서 대리자등을 이용해서 다른쪽에 함수 구현해서 이벤트 구독시키던거 생각하면 좀 불편하긴한데 비슷하게라도 쓸 수 있다.
뭐가 됐든 금요일에 Json으로 정신나갈뻔 했던 것보다는 훨씬 낫다.
public interface OnAttackListener {
void onAttack(String attacker, String target, int damage);
}
인터페이스로 미리 이벤트 틀을 구현해놓는다.
public class BattleSimulator {
private OnAttackListener listener;
// 콜백 등록
public void setOnAttackListener(OnAttackListener listener) {
this.listener = listener;
}
public void attack(String attacker, String target, int damage) {
System.out.println(attacker + " attacks " + target);
// 공격 처리 후 콜백 호출
if (listener != null) {
listener.onAttack(attacker, target, damage);
}
}
}
구현해놓은 이벤트 틀을 변수로 미리 잡아두고, 그걸 할당하는 함수를 구현해놓는다.
그리고 할당된게 있으면, 실행되도록 셋팅까지
public static void Q8()
{
BattleSimulator battle = new BattleSimulator();
battle.setOnAttackListener(new OnAttackListener() {
@Override
public void onAttack(String attacker, String target, int damage) {
System.out.println("[LOG] " + attacker + " dealt " + damage + " to " + target);
}
});
battle.attack("Hero", "Orc", 15);
}
setOnAttackListener의 매개변수를, 마치 c#의 무명함수처럼 해놓은 모습이다.
인터페이스였으니 @Override를 붙이고 구조를 구현해놓은 모습
Hero attacks Orc
[LOG] Hero dealt 15 to Orc
결과창
delegate, 무명함수 = 지루하고 현학적임, 코드 꼬이면 봐야할게 늘어남, 세상이 무너짐
람다식 = 금방끝남, 사전작업이 필요X
c#에서조차 지루하고 현학적인 무명함수따위는 개념만 배우고 바로 치워버리고 람다식을 갈겼던걸 생각하면 아주 그립다.
public static void Q8_1()
{
BattleSimulator battle = new BattleSimulator();
battle.setOnAttackListener(
(attacker, target, damage) -> {
System.out.println("[LOG] " + attacker + " -> " + target + " (" + damage + ")");
}
);
battle.attack("Hero", "Slime", 7);
}
물론 여기에도 람다식은 있지만, 문법이 살짝 다르다.
c#에선 => 였었을텐데
최소한 그 외의 괄호치고 안에 매개변수 써놓는 등의 문법은 다 똑같아보이니 다행이다.
Action과 Func
c#에서 대리자를 편하게 쓰게해줬던 1등공신들
Java에서도 있다
public class Player{
private String name;
private int level;
private int exp;
public Consumer<String> damageAction;
public void TestDamageAction(String test)
{
damageAction.accept(test);
}
public static void main(String[] args) throws Exception {
System.out.println("Hello, World!");
Player p_Test = new Player("asdf", 1,2);
p_Test.damageAction = (s) ->
{
System.out.println(s);
};
p_Test.TestDamageAction("asdf");
//Q8_1();
}
이름은 조금 다르지만, 매우 익숙한 그 형태를 보니 마음이 편안해지는것같다.
차이점은 .accept를 찍어야 사용이 된다는점
import java.util.function.Consumer;
그리고 이거 선언해놔야 작동한다는점
c#에서 대충 쓰면 위에거 자동으로 생성해줬었던걸 생각하면 이게 진짜 제일 불편하다.

그리고 c#에선 안에 들어갈수있는 매개변수를 그냥 미친듯이 만들어놔서 사실상 제한이 없었지만,
consumer 얘는 단 하나, 그리고 2개까지 쓸수있게 BiConsumer라는게 있다.
3개 이상부턴 없는데, 3개 이상 써야한다면 DTO를 만들어서 consumer에서 쓴다고한다

일반화 T
import java.util.ArrayList;
import java.util.List;
public class Box<T> {
List<T> box;
public Box()
{
this.box = new ArrayList<>();
}
public void add(T a)
{
box.add(a);
}
public void printAll() {
for (T item : box) {
System.out.print(item + " ");
}
System.out.println();
}
}
public static void Q9()
{
Box<Integer> box = new Box<>();
box.add(1);
box.add(2);
box.printAll();
}
1 2
이건 그냥 별 차이없는것같다.
인스턴스 생성할때 new Box<> << 이 괄호 안에 아무것도 안넣는거정도
List 생성할때부터 해서 왜 자꾸 변수타입이랑 옆에 인스턴스 형태가 다른건지 아주 화딱지가 난다
그리고 foreach가 없고,
for(T item : box)
변수 , 배열
이런 형태로 사용한다.