요약
- 오버로딩(Overloading)
- 같은 이름의 메서드나 생성자를 여러 개 정의하는 것입니다.
- 오버라이딩(Overriding)
- 상위 클래스에서 이미 정의된 메서드를 하위 클래스에서 재정의(다시 구현)하는 것을 의미합니다.
- 하이딩(Hiding)
- 서브클래스에서 슈퍼클래스의 정적 메서드를 재정의하는 것입니다.
- 잘 이해되지 않는다면 오버라이딩 개념에 static이 있으면 하이딩이라고 생각하시면 됩니다.
오버로딩(Overloading)
오버로딩(Overloading) 개념
오버로딩(Overloading)은 객체 지향 프로그래밍에서 사용되는 개념으로, 같은 이름의 메서드나 생성자를 여러 개 정의하는 것입니다.
각각의 메서드나 생성자는 서로 다른 매개변수 목록을 가져야 하고 이를 통해 동일한 작업을 수행하지만 다양한 매개변수를 처리할 수 있게 됩니다.
여기서 “서로 다른 매개변수 목록”은 매개변수의 개수, 타입 또는 순서를 의미합니다.
메서드나 생성자의 시그니처(signature)는 메서드나 생성자의 이름과 매개변수 목록으로 구성되는데, 오버로딩된 메서드나 생성자는 시그니처가 서로 달라야 합니다.
오버로딩은 코드의 가독성을 높이고 재사용성을 증가시키는 데 도움이 됩니다.
메서드나 생성자를 호출할 때 개발자는 동일한 이름을 사용하여 다양한 시나리오에 맞는 메서드를 선택할 수 있습니다.
오버로딩(Overloading) 특징
- 같은 이름의 다수의 메서드/생성자 정의
- 오버로딩은 같은 이름을 가진 메서드나 생성자를 여러 개 정의하는 것을 허용합니다.
- 매개변수의 다양성
- 오버로딩된 메서드나 생성자들은 서로 다른 매개변수를 허용하여 호출될 수 있습니다. 이는 메서드나 생성자의 사용을 유연하게 만들어줍니다.
- 반환 값이나 접근 제어자에 영향을 주지 않음
- 메서드의 반환 값이나 접근 제어자가 달라도, 매개변수 목록이 다르다면 오버로딩이 가능합니다.
- 정적(Static) 메서드도 오버로딩 가능
- 정적 메서드도 오버로딩될 수 있지만, 인스턴스 메서드와는 달리 정적 메서드는 클래스 수준에서 호출되기 때문에 오버로딩 시 인스턴스 상태를 고려할 필요가 없습니다.
오버로딩(Overloading) 예시 코드
public class Calculator {
// 정수형 덧셈 메서드
public int add(int a, int b) {
return a + b;
}
// 실수형 덧셈 메서드
public double add(double a, double b) {
return a + b;
}
// 세 개의 정수를 더하는 메서드
public int add(int a, int b, int c) {
return a + b + c;
}
// 문자열을 이어붙이는 메서드
public String add(String a, String b) {
return a + b;
}
// 정수와 실수를 더하는 메서드
public double add(int a, double b) {
return a + b;
}
}
오버라이딩(Overriding)
오버라이딩(Overriding) 개념
오버라이딩(Overriding)은 객체 지향 프로그래밍에서 사용되는 개념으로, 상위 클래스에서 이미 정의된 메서드를 하위 클래스에서 재정의(다시 구현)하는 것을 의미합니다.
오버라이딩은 상속 관계에 있는 클래스들 간에 발생하며, 하위 클래스가 상위 클래스의 동일한 메서드 이름, 매개변수 및 반환 유형을 가진 메서드를 제공하여 해당 메서드의 동작을 변경할 수 있도록 합니다.
오버라이딩은 코드의 유연성과 재사용성을 높이는 데 사용되며, 하위 클래스는 상위 클래스의 메서드를 필요에 맞게 수정하여 상위 클래스의 기능을 확장하거나 수정할 수 있습니다.
오버라이딩(Overriding) 특징
- 상속 관계 필요
- 오버라이딩은 상속 관계에 있는 클래스들 간에 발생합니다. 즉, 하위 클래스가 상위 클래스를 확장(상속)하는 경우에만 오버라이딩을 사용할 수 있습니다.
- 메서드 시그니처 일치
- 오버라이딩된 메서드는 상위 클래스의 메서드와 시그니처(이름, 매개변수, 반환 유형)가 동일해야 합니다.
- 동적 바인딩(실행 시간에 결정)
- 오버라이딩된 메서드는 객체의 실제 유형에 따라 호출됩니다. 이는 다형성(polymorphism)을 구현하는데 사용됩니다. 예를 들어, 상위 클래스 타입의 참조 변수로 하위 클래스 객체를 참조할 때, 오버라이딩된 메서드는 실제 객체의 타입에 따라 호출됩니다.
- 상위 클래스 메서드의 동작 변경
- 하위 클래스에서 오버라이딩된 메서드는 상위 클래스의 동일한 메서드를 재정의하여 동작을 변경할 수 있습니다.
이는 하위 클래스가 상위 클래스의 기능을 확장하거나 수정할 수 있도록 합니다.
- 하위 클래스에서 오버라이딩된 메서드는 상위 클래스의 동일한 메서드를 재정의하여 동작을 변경할 수 있습니다.
- super 키워드를 사용하여 상위 클래스 메서드 호출
- 하위 클래스에서 오버라이딩된 메서드 내에서 super 키워드를 사용하여 상위 클래스의 메서드를 명시적으로 호출할 수 있습니다.
오버라이딩(Overriding) 예시 코드
// 동물을 나타내는 부모 클래스
class Animal {
// 소리를 내는 메서드
public void makeSound() {
System.out.println("동물이 소리를 냅니다.");
}
}
// Animal 클래스를 상속받는 Dog 클래스
class Dog extends Animal {
// Animal 클래스의 makeSound 메서드를 오버라이딩하여 재정의
@Override
public void makeSound() {
System.out.println("멍멍!");
}
}
public class Main {
public static void main(String[] args) {
// Animal 클래스의 인스턴스 생성
Animal animal = new Animal();
// Animal 클래스의 makeSound 메서드 호출
animal.makeSound(); // 출력: 동물이 소리를 냅니다.
// Dog 클래스의 인스턴스 생성
Dog dog = new Dog();
// Dog 클래스에서 오버라이딩된 makeSound 메서드 호출
dog.makeSound(); // 출력: 멍멍!
// Animal 타입의 참조변수에 Dog 클래스의 인스턴스 할당
Animal abc = new Dog();
// Dog 클래스에서 오버라이딩된 makeSound 메서드 호출
abc.makeSound(); // 출력: 멍멍!
}
}
하이딩(Hiding)
하이딩(Hiding) 개념
하이딩(Hiding)은 메서드 오버라이딩과 비슷한 개념으로, 서브클래스에서 슈퍼클래스의 정적 메서드를 재정의하는 것입니다.
하이딩은 정적 메서드에만 적용되며, 서브클래스에서 슈퍼클래스의 정적 메서드를 “가리는” 것입니다. 이는 오버라이딩과는 달리 정적인 성격을 가지고 있습니다.
정적 메서드는 클래스 수준에서 호출되기 때문에 인스턴스의 상태에 따라 달라지지 않습니다.
간단히 말해, 서브클래스에서 정적 메서드를 재정의할 수 있지만, 실제로는 재정의된 것이 아니라 “가려진” 것입니다.
즉, 정적 메서드의 호출은 컴파일 시간에 해당하는 클래스의 메서드로 결정되며, 실행 시간에는 바뀌지 않습니다.
하이딩의 사용은 주로 정적 유틸리티 클래스의 메서드를 변경하거나 확장할 때 사용됩니다.
정적 메서드는 객체의 인스턴스와 관련이 없으므로 오버라이딩 되지 않으며 대신 하위 클래스에서 동일한 이름의 정적 메서드를 제공하여 상위 클래스의 메서드를 가려버립니다.
하이딩(Hiding) 특징
- 정적 바인딩(컴파일 시간에 결정)
- 하이딩된 메서드는 컴파일 시간에 해당하는 클래스의 메서드로 결정됩니다. 이는 오버라이딩된 메서드와 달리 실행 시간이 아니라 컴파일 시간에 결정됩니다.
- 메서드 시그니처 일치
- 하이딩된 메서드는 슈퍼클래스의 정적 메서드와 시그니처(이름, 매개변수, 반환 유형)가 동일해야 합니다.
- 메서드 호출은 클래스 타입에 의해 결정
- 하이딩된 정적 메서드의 호출은 참조 변수의 타입이 아니라 변수가 참조하는 클래스의 정적 메서드에 의해 결정됩니다.
하이딩(Hiding) 예시 코드
하이딩이 이해가지 않는다면 간단하게 오버라이딩 개념에 static이 있으면 하이딩이라고 생각하시면 됩니다.
class Parent {
static void display() {
System.out.println("부모 클래스의 display 메서드");
}
}
class Child extends Parent {
static void display() {
System.out.println("자식 클래스의 display 메서드");
}
}
public class Main {
public static void main(String[] args) {
Parent parent = new Child();
parent.display(); // 출력: "부모 클래스의 display 메서드"
}
}