![](https://blog.kakaocdn.net/dn/mJvGW/btsgG46RP4y/6GgJl8Bq3iA0KqDUwrRb60/img.png)
안녕하세요. 성조입니다.
이번 포스팅은 메서드 오버로딩(Overloading)과 오버라이딩(Overriding)에 대해서 정리하는 포스팅을 진행해 보려 합니다.
혹여나, 올바르지 못한 지식 전달 정보가 있다면 언제든지 댓글로 피드백 남겨주시면 감사드리겠습니다!
메서드 오버로딩과 오버라이딩 선 정리
- 같은 클래스 내에서 이뤄지며 메서드 이름은 같지만 매개변수의 유형이나 개수가 다른 것을 오버로딩(Overloading)이라 한다. 또한, 상속받은 메서드도 오버로딩 할 수 있다. 이 부분은 아래 설명을 조금 더 읽는 것을 권장한다.
- 상속 관계에 있는 클래스 간에 발생하며 메서드 이름, 매개변수 및 반환 타입이 모두 같은 것을 오버라이딩(Overriding)이라 한다.
[비교 정리 표]
비교 | 오버로딩(Overloading) | 오버라이딩(Overriding) |
메서드 선언 방법과 이름 | 같은 클래스나 상속 관계의 동일한 이름의 메서드로 동일하게 작성한다. | 자식(서브) 클래스가 부모(슈퍼) 클래스의 메서드와 동일하게 작성한다. 즉, 자식 클래스 위치에서 정의된다. |
매개변수, 타입 | 매개 변수와 타입을 다르게 한다. | 매개 변수 이름과 타입, 반환 타입이 모두 같아야 한다. 다른 특성을 띄우는 것은 오버로딩의 특징이다. |
메서드 선언 위치 | 부모 클래스에서 상속 받은 자식 클래스의 위치 또는 같은 클래스 내부에서 선언한다. | 부모 클래스의 메서드를 자식 클래스에서 선언한다. |
리턴 타입 | 매개변수 유형, 개수를 다르게 할 수 있다. 하지만 리턴 타입만 바꾸는 것은 오버 로딩이라 할 수 없다. | 자식 클래스는 부모 클래스에서 상속받은 메서드의 이름, 매개변수, 개수, 반환 타입이 모두 같아야 한다. |
final 메서드 | 다른 매개변수로 오버로드 하는 것은 허용 사항이다. | 재정의 하는 규칙이 적용되지 안되기 때문에 활용할 수 없다. |
static 메서드 | 오버로딩은 매개 변수의 유형과 개수를 다르게 할 수 있어서 같은 이름의 static 메서드를 가지더라도 가능하다. | 자식 클래스에서 부모 클래스의 static 메서드를 재정의해서 활용하면 컴파일러는 static 메서드를 새로운 메서드로 간주하고 처리한다. static 메서드가 클래스 레벨에서 호출되기 때문에 상속받은 오버라이딩의 개념과는 무관하게 되는 것이다. |
바인딩 | 정적 바인딩 된다. 호출될 메서드를 컴파일 단계에서 결정하는 것이다. | 동적 바인딩 된다. 런타임에서 호출될 메서드를 찾아서 호출한다. 런타임이란 실행 시간 정도로 요약한다. |
오버로딩(Overloading)이란?
class Overload {
void test() {
System.out.println("파라미터가 없는 경우.");
}
// 하나의 정수가 있는 오버로드 예제
void test(int a) {
System.out.println("a: " + a);
}
// 두 개의 정수가 있는 오버로드 예제
void test(int a, int b) {
System.out.println("a and b: " + a + "," + b);
}
}
오버로딩은 같은 클래스 내에서 같은 이름의 메서드를 여러 개 가지면서 매개변수의 유형과 개수를 다르게 하는 기능을 말한다.
2번 case
class Parent {
void display(int a) {
System.out.println("부모 클래스의 1개의 파라미터를 갖는 메서드를 가지는 경우.");
}
}
class Child extends Parent {
void display(int a, int b) {
System.out.println("자식 클래스의 2개의 파라미터를 갖는 메서드를 가지는 경우");
}
}
public class Test {
public static void main(String[] args) {
Child child = new Child();
child.display(1); // 부모 클래스의 메서드를 호출한다.
child.display(1, 2); // 자식 클래스의 메서드를 호출한다.
}
}
위와 같이 상속받아서 오버로딩을 작성할 수 있다.
오버라이딩(Overriding)이란?
class ParentClass {
void display() {
System.out.println("부모 클래스에 있는 값이다.");
}
}
class ChildClass extends ParentClass {
// 부모 메서드에 있는 것을 오버라이딩해서 재정의 활용한다.
void display() {
System.out.println("자식 클래스에 있는 값은 다른 값으로 대체한다.");
}
}
오버라이딩은 상속 관계에 잇는 클래스 간에 같은 이름과 매개변수를 가지면서 반환 타입이 같은 메서드를 자식 클래스에서 재정의하는 것을 말한다.
오버라이딩은 상위 클래스의 메서드를 하위 클래스의 요구 사항에 맞게 한번 더 활용하는 것으로 정리할 수 있다.
2번 case
class Animal {
public void makeSound() {
System.out.println("동물이 소리를 낸다.");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("고양이가 야옹거렸다.");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
animal.makeSound();
Cat cat = new Cat();
cat.makeSound();
}
}
오버로딩과 오버라이딩 한 조각 먹어보기.
메서드 오버로딩(Overloading)의 조건
1. 같은 클래스 내에서 메서드 이름은 반드시 같아야 한다.
2. 매개변수의 개수 또는 타입이 달라야 한다.
정적 바인딩을 통해서 컴파일러가 어떤 메서드를 호출할 것인지 정하는 것이므로 매개 변수의 개수와 타입이 다른 메서드로 오버로딩 되어야 한다. -> 중복되면 에러가 발생)
3. 반환 타입과 접근 제어자는 영향을 주지 않는다.
리턴 값만 다르게 갖는 메서드는 오버로딩과 무관하므로 위 반환 타입과 접근 제어자는 두 가지 요소는 메서드 오버로딩에 영향을 미치지 않는다.
메서드 오버라이딩(Overriding)의 조건
1. 상속 관계에 있는 두 클래스 간에 발생하는 개념으로 상속받아야 하며, 부모 클래스가 가지고 있는 메서드를 오버로딩할 때 자식 클래스도 이름을 반드시 같게 만들어야 한다.
2. 매개변수의 개수와 타입이 같아야 한다.
메서드 시그니처가 동일해야 한다.
메서드 시그니처는 메서드의 이름과 매개변수 목록을 말한다. 또한, 반환 타입은 메서드 시그니처에 포함되지 않는다.
오버로딩에서는 메서드 시그니처가 달라야 한다.
즉, 메서드 이름은 같지만, 매개변수 목록이 달라야 한다는 의미를 갖는다.
오버라이딩에서는 메서드 시그니처가 같아야 한다.
즉, 상속 관계에 있는 부모 클래스와 자식 클래스. 두 클래스가 모두 메서드 이름과 목록이 같아야 한다는 의미이다.
3. 반환 타입은 같거나, 부모 클래스 메서드의 반환 타입의 하위 타입이어야 한다.
다형성 원칙의 핵심 원칙이며, 다음과 같이 정리한다.
3 - 1) 반환 타입이 같은 경우.
시그니처가 부모 클래스와 일치함을 뜻한다.
3 - 2) 반환 타입이 부모 클래스의 반환 타입의 하위 타입의 경우.
자식 클래스는 더 구체적인(subtype) 반환 타입을 사용할 수 있다.
4. 부모 클래스의 메서드가 final로 선언되면 오버라이딩을 할 수 없다.
'final' 메서드는 마지막 메서드이므로 오버라이딩 단계에서 수정할 수 없다. (오버라이딩 자체가 런타임 단계에서 시작되는 것을 인지하자.)
5. 부모 클래스의 메서드가 static으로 선언되면 오버라이딩할 수 없다.
static 메서드의 경우 클래스 레벨에서 바인딩되므로 오버라이딩 적용이 불가능하다.
6. 오버라이딩 하는 메서드의 접근 지정자 수준은 자식 클래스가 부모 클래스보다 같거나 더 포괄적인 접근 지정자를 가져야 한다.
예시) 부모 클래스 메서드가 protected의 접근 지정자를 가지고 있다면. 자식 클래스는 오버라이딩 메서드로 protected 또는 public 접근 지정자를 활용해야 한다.
오버로딩(Overloading)의 장점 및 단점
[장점]
코드의 가독성 : 메서드 이름을 다양한 맥락에서 재사용할 수 있다.
코드의 재사용 : 매개변수 유형과 개수가 다른 동일한 작업을 수행하는 메서드를 오버로드할 수 있다. -> 코드 중복을 최소화하고 기능을 재사용할 수 있다.
[단점]
복잡성 : 재정이 된 메서드들의 이름이 같고, 많아지면 복잡성의 문제가 발생한다. 개발자가 올바른 메서드를 호출하기 위해서 하나의 메서드 명으로 오버로드된 메서드가 일정 개수 이상을 넘어가면 오히려 코드를 읽고 이해하는데 많은 혼란을 주게 된다. 또한, 본인이 의도한 메서드가 아닌. 잘못된 메서드를 호출할 가능성이 높아지는 단점이 있다.
오버라이딩(Overriding)의 장점 및 단점
[장점]
런타임 다형성 : 상속 관계에서 오버라이딩을 사용하면, 런타임에 객체에 따라 적절한 메서드가 실행되는 장점이 있다. 객체지향의 다형성을 활용한 방법 중 하나가 된다.
메서드 재정의 : 오버라이딩의 경우. 같은 클래스에서 호출하여 활용하는 오버로드와 다르게 상속을 통해서 부모 클래스와 자식 클래스로 나눠질 때 각 같은 공통 속성을 공유하고, 각자의 맞는 특성의 요구 사항을 메서드 재정의를 통해서 분배할 수 있는 것이 장점이다.
코드의 재사용 : 공통되는 메서드를 부모 클래스에서 정의하고, 자식 클래스에서 재정의하여 중복 코드를 줄일 수 있게 된다.
[단점]
런타임 오류 : 런타임 다형성이 장점이면서 단점으로 적용될 수 있다. 오버라이딩 된 메서드는 컴파일 타임이 아닌 런타임에 바인딩되는데 잘못된 메서드 오버라이딩이 존재하면 런타임 오류가 발생하여 디버깅으로 잡아내기 어려운 부분이 발생할 수 있다.
유지 보수 문제 : 하위 클래스에서 메서드를 오버라이드 할 때는 하위 클래스의 메서드가 상위 클래스의 메서드와 동일한 기능을 해야 하는지, 아니면 수정되어야 하는지 판단하기 어려울 수도 있다. 굳이 자식 클래스에서 나눠야 하는지 의문이 들 수 있다는 것이다.
혹여나 불필요한 부분에 추가된다면 코드 유지 보수를 하는 과정을 오히려 까다롭게 만들어서 기술 부채가 발생할 수 있다.
향후 바인딩에 대한 포스팅을 추가적으로 다룰 예정이지만 간략하게 설명을 남긴다.
바인딩(Binding)
정적 바인딩(Static Binding)
컴파일 시간에 호출될 메서드를 결정하는 것이다. 오버 로딩된 메서드는 컴파일 단계에서 인자의 개수와 타입에 기반하여 어떤 메서드가 호출될 것인지 결정되는 바인딩을 의미한다.
동적 바인딩(Dynamic Binding)
런타임 시간에 호출될 메서드를 결정하는 것이다. 오버라이딩된 메서드는 호출하는 객체의 실제 타입에 기반하여 어떤 메서드가 호출될지 결정된다. 동적 바인딩의 문제로 런타임 시간에 호출되면서 에러가 발생하면 정적 바인딩보다 에러를 찾아내는데 조금 더 시간이 소요될 수 있다.
오타 또는 설명이 이상한 부분, 궁금한 부분이 있다면 언제든지 댓글 남겨주시면 감사드리겠습니다!
다음 포스팅 때 뵙겠습니다!
'Java ☕ > Java' 카테고리의 다른 글
[Java] 박싱(Boxing)과 언박싱(Unboxing) (0) | 2023.05.28 |
---|---|
[Java] Call by Value와 Call by Reference 정리. (값 호출과 참조 호출.) (0) | 2023.05.24 |
[Java] 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) (0) | 2021.12.14 |
[Java] 변수(Variable)와 상수(constant) (1) | 2021.11.30 |
Java의 장단점 (0) | 2021.11.10 |