메서드 오버라이딩 문서의 구현 코드다.
// 실행: docker run --rm -v "$PWD":/w -w /w eclipse-temurin:21-jdk java 22_java-overriding_impl.java
// (JDK 21. 파일 이름이 숫자로 시작해 public 클래스를 두지 않는다. 맨 위 클래스의 main이 돈다.)
// 문서 「메서드 오버라이딩」의 예제 출력과 카드 답을 실제 실행 결과와 비교한다.
class OverridingCheck {
// 문서의 Parent / Child
static void trace() {
Child child = new Child();
child.method1();
child.method2();
child.method3();
}
// 변수 타입이 부모여도 실제 객체의 메서드가 돈다
static void dynamic() {
Parent p = new Child();
p.method2();
Parent q = new Parent();
q.method2();
}
// super.method()로 가려진 부모 메서드를 부른다
static void superCall() {
new Worker().method();
}
// 매개변수를 다르게 쓰면 오버라이딩이 아니라 오버로딩이다
static void notOverride() {
Animal a = new LoudDog();
a.makeSound();
LoudDog d = new LoudDog();
d.makeSound(2);
}
// 카드 C2
static void card() {
new Y().run();
}
public static void main(String[] args) {
check("trace", capture(OverridingCheck::trace), "Parent.method1\nChild.method2\nChild.method3\n");
check("dynamic", capture(OverridingCheck::dynamic), "Child.method2\nParent.method2\n");
check("super call", capture(OverridingCheck::superCall), "작업 처리1\n작업 처리2\n");
check("not override", capture(OverridingCheck::notOverride), "Some sound\nBark Bark \n");
check("card C2", capture(OverridingCheck::card), "X\nY\n");
System.out.println("ALL CHECKS PASSED");
}
static String capture(Runnable r) {
java.io.PrintStream old = System.out;
java.io.ByteArrayOutputStream buf = new java.io.ByteArrayOutputStream();
System.setOut(new java.io.PrintStream(buf));
try { r.run(); } finally { System.setOut(old); }
return buf.toString();
}
static void check(String name, String got, String want) {
if (!got.equals(want)) throw new AssertionError(name + "\n--- got ---\n" + got + "--- want ---\n" + want);
System.out.print("[" + name + "]\n" + got);
}
}
class Parent {
void method1() { System.out.println("Parent.method1"); }
void method2() { System.out.println("Parent.method2"); }
}
class Child extends Parent {
@Override
void method2() { System.out.println("Child.method2"); }
void method3() { System.out.println("Child.method3"); }
}
class Base {
public void method() {
System.out.println("작업 처리1");
}
}
class Worker extends Base {
@Override
public void method() { // public을 빼면 접근 범위가 좁아져 컴파일되지 않는다
super.method();
System.out.println("작업 처리2");
}
}
class Animal {
public void makeSound() {
System.out.println("Some sound");
}
}
class LoudDog extends Animal {
// @Override를 붙이면 컴파일 오류가 난다. 매개변수가 달라 다른 메서드다
public void makeSound(int times) {
for (int i = 0; i < times; i++) {
System.out.print("Bark ");
}
System.out.println();
}
}
class X {
void hi() { System.out.println("X"); }
void run() { hi(); }
}
class Y extends X {
@Override
void hi() {
super.hi();
System.out.println("Y");
}
}