오버로딩(Overloading)
오버로딩은 하나의 클래스에서 같은 이름의 메서드를 여러 개 정의하는 것이다. 매개변수의 타입이나 개수를 다르게 정의함으로써 여러 개의 메서드를 정의한다. 메서드의 반환타입이 다른 경우는 오버로딩으로 간주하지 않는다. 그 이유는 메서드가 호출된 시점에 어떤 메서드가 호출된 것인지 컴파일러가 결정할 수 없기 때문이다.
public class Overloading {
public void test () {
System.out.println("매개변수가 없는 test 메서드 실행");
}
public void test (int x) {
System.out.println("매개변수가 int 타입의 " + x + "인 메서드 실행");
}
public void test (double x) {
System.out.println("매개변수가 double 타입의 " + x + "인 메서드 실행");
}
// public double test (double x) { 컴파일 에러, 반환타입이 다른 경우는 오버로딩으로 간주하지 않는다.
// System.out.println("매개변수가 double 타입의 " + x + "인 메서드 실행");
// return x;
// }
public void test (int x, int y) {
System.out.println("매개변수가 int 타입의 " + x + ", " + y + "인 메서드 실행");
}
public void test (double x, int y) {
System.out.println("매개변수가 double 타입의 " + x + ", int 타입의 " + y + "인 메서드 실행");
}
public void test (int x, double y) {
System.out.println("매개변수가 int 타입의 " + x + ", double 타입의 " + y + "인 메서드 실행");
}
}
public class App {
public static void main(String[] args) {
Overloading overloading = new Overloading();
overloading.test(5);
overloading.test(2.5);
overloading.test(5, 10);
overloading.test(2.5, 5);
overloading.test(5, 2.5);
}
}
/* 실행결과
매개변수가 int 타입의 5인 메서드 실행
매개변수가 double 타입의 2.5인 메서드 실행
매개변수가 int 타입의 5, 10인 메서드 실행
매개변수가 double 타입의 2.5, int 타입의 5인 메서드 실행
매개변수가 int 타입의 5, double 타입의 2.5인 메서드 실행
*/
test(int x, double y)와 test(double x, int y)는 int 타입과 double 타입의 매개변수가 정의되어 있고 그 순서만 다르다. 이 경우에는 매개변수 값에 의해 어떤 메서드가 호출되어야 할지 결정할 수 있으므로 오버로딩으로 간주한다.
오버라이딩(Overriging)
오버라이딩은 상위 클래스의 메서드를 하위 클래스에서 '재정의'하는 것이다. 상속 및 구현 관계에 있는 여러 개의 클래스에서 적용되는 문법이다. 구현부를 재정의하는 것이기 때문에 메서드의 반환 타입, 매개 변수, 메서드 이름은 같아야 한다. 달리 말해, 메서드의 선언부는 같고 구현부는 달라야 한다.
public class Vehicle {
public void move() {
System.out.println("탈것이 움직입니다.");
}
}
public class Car extends Vehicle {
public void move() {
System.out.println("[자동차]가 움직입니다.");
}
}
public class AirPlane extends Vehicle {
public void move() {
System.out.println("[비행기]가 움직입니다.");
}
}
public class App {
public static void main(String[] args) {
Vehicle vehicle1 = new Vehicle();
Vehicle vehicle2 = new Car();
Vehicle vehicle3 = new AirPlane();
vehicle1.move();
vehicle2.move();
vehicle3.move();
}
}
/* 실행 결과
탈것이 움직입니다.
[자동차]가 움직입니다.
[비행기]가 움직입니다.
*/
Car와 AirPlane 클래스는 Vehicle의 하위 클래스이며 move() 메서드를 오버라이딩했다. main() 메서드에서 생성된 Car와 AirPlane의 인스턴스의 주소값은 그 상위 클래스인 Vehicle 타입의 참조변수에 저장된다. 따라서, 참조변수 vehicle2의 타입은 Vehicle이지만 저장된 인스턴스는 Car타입이기 때문에 vehicle2.move() 코드가 실행될 때 Car 클래스에서 오버라이딩 된 move() 메서드가 호출된다. 참조변수 vehicle3도 마찬가지이다.
정리
| 구분 | 오버로딩 (Overloading) | 오버라이딩 (Overrriding) |
| 접근 제어자 | 모든 접근 제어자를 사용할 수 있다. | 상위 클래스의 메서드보다 좁은 범위로 설정할 수 없다. |
| 메서드 이름 | 동일해야 한다. | 동일해야 한다. |
| 반환타입 | 상관없다. | 동일해야 한다. |
| 매개변수 개수 | 달라야 한다. | 동일해야 한다. |
| 매개변수 타입 | 달라야 한다. | 동일해야 한다. |
| 적용범위 | 한 개의 클래스 | 상속, 구현 관계에 있는 여러 개의 클래스 |
오버로딩과 오버라이딩은 이름만 비슷할 뿐, 그 차이는 명백하다. 오버로딩은 이름이 같은 새로운 메서드를 정의하는 것이고, 오버라이딩은 상속받은 메서드의 내용을 변경하는 것이다. 두 문법 모두 객체지향 프로그래밍의 주요 특징인 '다형성'을 구현하기 위한 수단이다. 다형성은 하나의 클래스나 메서드가 상황에 따라 다른 동작을 하는 성질이다.
오버로딩이 필요한 이유는 println() 메서드를 보면 쉽게 이해할 수 있다. 반면, 오버라이딩이 필요한 이유는 오버라이딩만 배워서는 쉽게 와닿지 않는다. 이 부분은 참조변수 형변환과 상속을 통한 다형성 구현과 함께 설명할 때 보다 이해하기 쉬울 것이다. 이는 추후에 다루도록 한다.
'Java' 카테고리의 다른 글
| [Java] 서블릿(Servlet)의 개념과 동작 과정 (0) | 2023.08.13 |
|---|---|
| [Java] 상속과 참조변수 형변환을 활용한 다형성 구현 (0) | 2023.04.29 |
| [Java] 메서드의 기본형 매개변수와 참조형 매개변수 (0) | 2023.04.13 |
| [Java] 클래스를 바라보는 두 가지 관점 (0) | 2023.04.12 |
| [Java] Java의 특징과 Java 프로그램 실행 과정 (0) | 2023.04.10 |