
이번 글에서는 자바 프로그래밍을 하다 보면 한 번쯤은 마주했을 오버로드와 오버라이드에 대해 정리해볼 것이다.
먼저 사전적 정의부터 보도록 하자.
자바의 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메소드가 있더라도 매개변수의 개수 또는 타입이 다르면 같은 이름을 사용해서 메소드를 정의할 수 있다.
[오버로딩의 조건]
오버로딩의 조건은 메소드의 이름이 같고 매개변수의 개수나 타입이 달라야 한다.
여기서 주의할 점은 Return값만 다른 것은 오버로딩할 수 없다는 것이다.
아래 코드를 예로 들어 살펴보자.
class OverloadingTest {
public static void main(String[] args) {
OverloadingMethods om = new OverloadingMethods();
om.print();
System.out.println(om.print(3));
om.print("Hello!");
System.out.println(om.print(4, 5));
}
}
class OverloadingMethods {
public void print() {
System.out.println("오버로딩1");
}
String print(Integer a) {
System.out.println("오버로딩2");
return a.toString();
}
void print(String a) {
System.out.println("오버로딩3");
System.out.println(a);
}
String print(Integer a, Integer b) {
System.out.println("오버로딩4");
return a.toString() + b.toString();
}
}
[결과]
오버로딩1
오버로딩2
3
오버로딩3
Hello!
오버로딩4
45
위 코드는 문제없이 잘 실행된다.
print라는 이름의 메소드 4개가 매개변수의 개수와 타입을 다르게 지정하면 정상적으로 잘 구현된다는 것을 보여준다. 또한 접근 제어자도 자유롭게 지정해줄 수 있는데 각 메소드의 접근 제어자를 public, default, protected, private으로 다르게 지정해줘도 상관없다는 것이다.
다만 접근 제어자만 다르게 한다고 오버로딩이 가능하다는 것은 아니다.
따라서 오버로딩은 매개변수의 차이로만 구현할 수 있다는 것으로 매개변수가 다르면 리턴값은 다르게 지정할 수 있다.
1. 같은 기능을 하는 메소드를 하나의 이름으로 사용할 수 있다.
흔히 콘솔창에 텍스트를 출력할 때 사용하는 println이라는 메소드를 대표적인 예로 들 수 있다. 실은 이 메소드가 오버로딩의 결정체인데 우리는 println의 인자 값으로 int, double, boolean, String 등 아주 다양한 타입의 매개변수들을 집어넣어도 '출력'의 기능을 가진 메소드로 정의가 된다.
2. 메소드의 이름을 절약할 수 있다.
메소드를 매개변수의 종류에 따라 다르게 지정해야 한다면 수많은 메소드들의 이름을 정해줘야 할 것이다.
부모 클래스로부터 상속받은 메소드를 자식 클래스에서 재정의하는 것.
상속받은 메소드를 그대로 사용할 수도 있지만 자식 클래스에서 상황에 맞게 변경해야 하는 경우 오버라이딩할 필요가 생긴다.
[오버라이딩의 조건]
오버라이딩은 부모 클래스의 메소드를 재정의하는 것이므로 자식 클래스에서는 오버라이딩하고자 하는 메소드의 이름, 매개변수, 리턴값이 모두 같아야 한다.
public class OverridingTest {
public static void main(String[] args) {
Person person = new Person();
Child child = new Child();
Senior senior = new Senior();
person.cry();
child.cry();
senior.cry();
}
}
class Person {
void cry() {
System.out.println("흑흑");
}
}
class Child extends Person {
@Override
protected void cry() {
System.out.println("잉잉");
}
}
class Senior extends Person {
@Override
public void cry() {
System.out.println("훌쩍훌쩍");
}
}
<결과>
흑흑
잉잉
훌쩍훌쩍
이는 어노테이션(Annotation)으로 주석이라는 뜻이다. 그러나 일반적인 주석과는 다르게 검증하는 기능을 가지고 있다. 여기서 사용되는 @Override는 오버라이딩을 검증하는 기능을 한다. 코드상으로 검사했을 때 오버라이딩이 실제로 시행되지 않았다면 컴파일시 오류를 출력한다.
위 코드는 정상적으로 실행되는 것을 확인할 수 있는데 부모 클래스의 메소드를 오버라이딩하는 것은 내용만을 새로 정의하는 것이므로 선언부는 부모의 것과 완벽히 동일해야 하는 것을 볼 수 있다.
사용자가 Person 클래스의 cry 메소드를 '흑흑'이라고 정의했다. 그런데 Child 클래스와 Senior 클래스를 만들면서 울음소리를 다르게 출력하고 싶은 것이다. 따라서 Child 클래스와 Senior 클래스에서 부모의 메소드 이름만 빌려와 자기의 방식대로 재정의하였다.
이것은 '오버라이딩'이라 한다.
여기서 접근 제어자를 다르게 설정해 놓은 것을 볼 수 있는데 오버라이딩에서 접근 제어자를 설정하는 규칙이 있다.
-부모 클래스의 접근 제어자는 default로 설정되어 있다. 여기서 자식 클래스들은 default보다 같거나 더 넓은 범위의 접근 제어자만 설정할 수 있으므로 default, protected, public 세 개의 접근 제어자는 사용 가능하다.
둘은 사실 이름만 비슷하지 완전히 다른 개념이다.

오버로딩 - 기존에 없는 새로운 메소드를 추가하는 것
오버라이딩 - 상속받은 메소드를 재정의하는 것