오버로딩 (메서드 오버로딩 / 생성자 오버로딩 / 문제점 & 해결책)
📍 메서드 오버로딩 (Method Overloading)
– 파라미터는 다르고 이름은 동일한 메서드를 여러번 정의하는 것.
– 비슷한 기능을 수행하지만 전달받은 데이터의 타입이 다른 경우,
메서드 이름을 따로 정의하지 않고 동일한 이름으로 파라미터만으로 구분되는 메서드를 여러개 정의하는 것.
– 주의! 메서드 시그니처(이름 / 리턴타입 / 파라미터 / 접근제한자)중 파라미터를 제외한 나머지는 동일하게 정의함.
→ 외부에서 메서드를 호출하는 시점에
이름이 동일한 메서드 간에 전달되는 데이터(파라미터)만으로 각 메서드가 구분되어야 함.
▸ 메서드 오버로딩 규칙 (택 1)
1. 메서드 파라미터의 데이터타입이 달라야 함.
2. 메서드 파라미터의 개수가 달라야 함. (파라미터가 없는 메서드도 해당)
EX )
• 오버로딩 X
// 클래스 생성
class NormalMethod{
// 두 수를 전달받아 덧셈 결과를 출력하는 메서드 정의
// int형 정수 2개 전달
public void add(int num1, int num2) {
System.out.println(num1 + num2);
}
// double형 실수 2개 전달
public void addDouble(double num1, double num2) {
System.out.println(num1 + num2);
}
}
– 일반적으로 메서드명도 식별자에 해당되므로 중복이 불가능함.
– 따라서 오버로딩을 하지 않을 경우
add()와 addDouble() 메서드는 하는 일이 같지만, 서로 다른 파라미터를 전달받으므로 다른 이름으로 정의해야 함.
– 메서드 정의 시 메서드명을 달리해야하므로 호출 시 구분이 불편할 수 있음.
// 인스턴스 생성
NormalMethod nm = new NormalMethod();
nm.add(10, 20);
// nm.add(1.0, 3.14); // double, double타입은 전달 불가.
nm.addDouble(1.0, 3.14); // 타입에 맞는 별도의 메서드를 호출해야 함.
– 인스턴스를 생성하여 정수 2개를 전달 받는 add메서드를 호출하여 정수 데이터를 파라미터에 전달하니 출력 잘 됨.
그러나 add메서드는 파라미터로 정수형 데이터만 받게끔 해놨으므로 double타입은 전달 불가.
– double타입은 double타입을 파라미터로 전달 받는 addDouble 메서드를 따로 호출해아함.
– add 메서드나 addDouble 메서드나 두 수를 전달받아 더하는 기능은 똑같으나,
데이터 타입에 따라 매번 다른 메서드를 호출해야하므로 불편함.
✓ 실행 결과
30
4.140000000000001
• 오버 로딩 O
// 클래스 생성
class OverloadingMethod{
// 정수 2개 전달
public void add(int num1, int num2) {
System.out.println("add(int, int) 호출");
System.out.println(num1 + num2);
}
// 실수 2개 전달 → 데이터타입 다름
public void add(double num1, double num2) {
System.out.println("add(double, double) 호출");
System.out.println(num1 + num2);
}
// 정수 3개 전달 → 개수 다름
public void add(int num1, int num2, int num3) {
System.out.println("add(int, int, int) 호출");
System.out.println(num1 + num2 + num3);
}
}
– 메서드의 이름은 add로 모두 동일하나, 파라미터로 전달 받는 데이터의 타입과 개수가 저마다 다름.
// 인스턴스 생성
OverloadingMethod om = new OverloadingMethod();
– 오버로딩 된 메서드 호출 시 파라미터를 전달하면,
오버로딩 메서드 중에서 파라미터가 일치하는 메서드가 자동 호출됨.
→ 단, 메서드 호출 시점에서 각 메서드가 구분되어야 오버로딩 성립.
om.add(10, 20);
– 자동완성으로 파라미터가 double타입인걸 선택해도 int타입을 넣으면 알아서 파라미터가 int타입인 메서드가 호출됨.
✓ 실행 결과
add(int, int) 호출
30
om.add(1, 2, 3);
– 자동으로 정수 3개를 파라미터로 전달 받는 메서드가 호출됨.
✓ 실행 결과
add(int, int, int) 호출
6
📍 생성자 오버로딩
– 메서드 오버로딩과 동일.
– 생성자 호출시 다양한 형태의 파라미터를 전달하여, 객체를 다양하게 초기화 하는 목적.
EX )
class Person{
String nation;
String name;
String jumin;
// 기본 생성자
public Person() {
System.out.println("Person() 생성자 호출");
}
// 파라미터 2개
public Person(String newName, String newJumin) {
System.out.println("Person(String, String) 생성자 호출");
nation = "대한민국";
name = newName;
jumin = newJumin;
}
– 국가는 자동으로 "대한민국"으로 초기화하고, 파라미터 2개(name, jumin)를 전달받아 초기화하는 생성자 정의함.
// 파라미터 3개
public Person(String newNation, String newName, String newJumin) {
System.out.println("Person(String, String, String) 생성자 호출");
nation = newNation;
name = newName;
jumin = newJumin;
}
– 파라미터 3개(nation, name, jumin)를 전달받아 초기화하는 생성자 정의함.
// 메서드 정의
public void showPersonInfo() {
System.out.println("국가 : " + nation);
System.out.println("이름 : " + name);
System.out.println("주민번호 : " + jumin);
}
}
– 국가명, 이름, 주민번호를 출력하는 showPersonInfo() 메서드를 정의함.
// 인스턴스 생성
Person p = new Person("한국", "홍길동", "041010-3123456");
p.showPersonInfo();
System.out.println("------------------");
– 인스턴스를 생성하여 파라미터에 문자열 3개를 모두 전달할 경우,
이름, 주민번호, 국가 모든 데이터가 파라미터로 전달받은 값으로 초기화 되는 생성자를 자동으로 호출함.
✓ 실행 결과
Person(String, String, String) 생성자 호출
국가 : 한국
이름 : 홍길동
주민번호 : 041010-3123456
------------------
Person p2 = new Person("홍길동", "041010-3123456");
p2.showPersonInfo();
System.out.println("------------------");
– 새로운 인스턴스 p2를 생성하여 문자열 2개만 전달할 경우,
이름과 주민번호만 초기화, 국가는 "대한민국"으로 초기화하는 생성자를 자동으로 호출함.
✓ 실행 결과
Person p3 = new Person();
– 파라미터 생성자를 하나라도 정의할 경우, 컴파일러에 의해 기본 생성자가 자동으로 생성되지 않음.
→ 따라서 기본 생성자를 호출해야 한다면, 직접 기본 생성자를 정의해야 함.
EX2 )
• 날짜를 관리하는 MyDate 클래스 정의하기
– 멤버변수 : 연도(year, 정수), 월(month, 정수), 일(day, 정수)
– 생성자
1. 기본 생성자 : 2023년 3월 7일로 초기화.
2. 파라미터 생성자
1 ) 연도(year)를 전달받아 초기화하고, 3월 7일로 초기화.
2 ) 연도(year), 월(month)을 전달받아 초기화하고, 7일로 초기화.
3 ) 연도(year), 월(month), 일(day)을 전달받아 초기화.
class MyDate{
// 멤버변수
int year;
int month;
int day;
// 파라미터가 없는 생성자
public MyDate() {
year = 2023;
month = 3;
day = 7;
}
// 파라미터 1개
public MyDate(int newYear) {
year = newYear;
month = 3;
day = 7;
}
// 파라미터 2개
public MyDate(int newYear, int newMonth) {
year = newYear;
month = newMonth;
day = 7;
}
// 파라미터 3개
public MyDate(int newYear, int newMonth, int newDay) {
year = newYear;
month = newMonth;
day = newDay;
}
}
• 인스턴스 생성하기
MyDate d1 = new MyDate();
System.out.println(d1.year + "/" + d1.month + "/" + d1.day);
MyDate d2 = new MyDate(2023);
System.out.println(d2.year + "/" + d2.month + "/" + d2.day);
MyDate d3 = new MyDate(2023, 3);
System.out.println(d3.year + "/" + d3.month + "/" + d1.day);
MyDate d4 = new MyDate(2023, 3, 7);
System.out.println(d4.year + "/" + d4.month + "/" + d4.day);
✓ 실행 결과
2023/3/7
2023/3/7
2023/3/7
2023/3/7
📍 메서드 오버로딩 문제점 & 해결책
▸ 문제점
– 동일한 작업을 수행하는 코드들의 중복이 발생.
→ 특정 메서드의 코드를 수정해야 하는 경우, 동일한 코드를 여러번 수정해야하는 번거로움 발생할 수 있음.
→ 코드의 유지보수성이 나쁨.
▸ 해결책
– 오버로딩 된 메서드에서 또 다른 오버로딩 된 메서드를 호출하여, 중복되는 작업을 대신 처리하도록 할 수 있음.
→ 메서드 호출 시 자신의 전달받은 파라미터를 다시 전달.
→ 이처럼 클래스 내의 다른 메서드를 호출하여 사용 = 코드의 재사용.
EX )
• PrintClass 생성하기
– 최대 3명까지의 초대 인원에 대한 이름을 입력받아 출력하는 print()메서드 정의.
단, 입력되지 않은 이름은 "없음"으로 출력.
ex ) print("홍길동", "이순신", "강감찬") 형태로 호출 시, 초대 멤버 : "홍길동 이순신 강감찬" 출력
print("홍길동") 형태로 호출 시, 초대 멤버 : "홍길동 없음 없음" 출력
print() 형태로 호출 시, 초대 멤버 "없음 없음 없음" 출력
class PrintClass {
public void print() {
System.out.println("print() 메서드 호출");
// System.out.println("초대 멤버 : 없음 없음 없음");
print("없음", "없음", "없음");
}
– print(String, String, String) 메서드를 호출(제일 마지막 메서드)하여, "없음, 없음, 없음" 문자열을 대신 출력.
public void print(String name1) {
System.out.println("print(String) 메서드 호출");
// System.out.println("초대 멤버 : " + name1 + " 없음 없음");
print(name1, "없음", "없음");
}
– print(String, String, String) 메서드를 호출하여, 전달받은 이름(name1), 없음, 없음 문자열을 대신 출력.
public void print(String name1, String name2) {
System.out.println("print(String, String) 메서드 호출");
// System.out.println("초대 멤버 : " + name1 + " " + name2 + " 없음");
print(name1, name2, "없음");
}
– 2명의 이름과 "없음" 문자열을 직접 출력하지 않고,
3명의 이름을 전달받아 출력하는 print(String, String, String) 메서드를 호출하여,
2명의 이름과 "없음" 문자열을 전달하면 대신 출력 가능.
public void print(String name1, String name2, String name3) {
System.out.println("print(String, String, String) 메서드 호출");
System.out.println("초대 멤버 : " + name1 + " " + name2 + " " + name3);
// print(name1, name2, name3); // 재귀 호출
}
}
– 주의! 모든 파라미터를 전달받는 마지막 메서드는 자기 자신을 호출하지 않고 반드시 직접 작업을 수행해야 함.
→ 재귀 호출 시 에러 발생하여 주석 처리함.