오버로딩과 오버라이딩, 다형성에 대해 학습하고 응용 문제를 풀어 보았다.
이전에 작업했던 전화번호부 3단계에서 추가 요소를 적용한 문제이다.
전화번호부 입력 단계에서 일반 / 대학 / 회사 중 선택하여 입력할 수 있으며,
검색, 추가, 전체출력 기능을 제공한다.
public class PhoneInfo {
private String name;
private String phoneNum;
PhoneInfo (String name, String phoneNum) {
this.name = name;
this.phoneNum = phoneNum;
}
public void showPhoneInfo() { // 오버라이딩: 재정의
System.out.println("이름 : " + name);
System.out.println("전화번호 : " + phoneNum);
}
public String getName() {
return name;
}
}
부모 클래스이자, <1.일반> 주소록이다.
이름과 전화번호만 입력받는다.
마찬가지로 이름 검색을 위해 게터를 생성했다.
public class PhoneUnivInfo extends PhoneInfo {
private String major;
private int grade;
PhoneUnivInfo (String name, String phoneNum, String major, int grade) {
super(name, phoneNum);
this.major = major;
this.grade = grade;
}
@Override
public void showPhoneInfo() { // 오버라이딩: 재정의
super.showPhoneInfo();
System.out.println("전공 : "+major);
System.out.println("학년 : "+grade);
}
}
자식 클래스이자, <2. 대학> 주소록이다.
부모 클래스인 일반 주소록을 오버라이딩했다.
public class PhoneCompanyInfo extends PhoneInfo {
private String company;
PhoneCompanyInfo(String name, String phoneNum, String company) {
super(name, phoneNum);
this.company = company;
}
@Override
public void showPhoneInfo() { // 오버라이딩: 재정의
super.showPhoneInfo();
System.out.println("회사 : "+company);
}
}
자식 클래스이자, <3. 대학> 주소록이다.
마찬가지로 부모 클래스에서 오버라이딩했다.
public class PhoneBookManager {
// 최대 10개까지 저장할 수 있는 전화번호부 배열을 생성
PhoneInfo[] phoneList = new PhoneInfo[10];
int cnt = 0; // phoneList[cnt] 배열의 카운트 변수
public void readData() {
System.out.println("데이터 입력을 시작합니다.");
System.out.println("1.일반, 2.대학, 3.회사");
int kinds; //입력받을 숫자 = 전화번호부 카테고리
kinds = PhoneBook.sc.nextInt();
PhoneBook.sc.nextLine();
PhoneInfo pi = null; // 연락처를 입력받을 pi객체 생성 및 초기화
switch (kinds) { // 각 메소드에서 리턴된 값을 pi에 넣어줌
case 1:
pi = readPhoneBook();
break;
case 2:
pi = readUnivBook();
break;
case 3:
pi = readCompanyBook();
break;
}
phoneList[cnt++] = pi; // 값이 들어간 pi를 phoneList 배열 안에 넣는 작업
System.out.println("데이터 입력이 완료되었습니다.");
}
// readData 에서 각각 일반, 대학, 회사의 데이터 입력을 처리할 메소드 생성
public PhoneInfo readPhoneBook() {
System.out.print("이름 : ");
String name = PhoneBook.sc.nextLine();
System.out.print("전화번호 : ");
String phoneNum = PhoneBook.sc.nextLine();
return new PhoneInfo(name, phoneNum);
}
public PhoneInfo readUnivBook() {
System.out.print("이름 : ");
String name = PhoneBook.sc.nextLine();
System.out.print("전화번호 : ");
String phoneNum = PhoneBook.sc.nextLine();
System.out.print("전공 : ");
String major = PhoneBook.sc.nextLine();
System.out.print("학년 : ");
int grade = PhoneBook.sc.nextInt();
return new PhoneUnivInfo(name, phoneNum, major, grade);
}
public PhoneInfo readCompanyBook() {
System.out.print("이름 : ");
String name = PhoneBook.sc.nextLine();
System.out.print("전화번호 : ");
String phoneNum = PhoneBook.sc.nextLine();
System.out.print("회사 : ");
String grade = PhoneBook.sc.nextLine();
return new PhoneCompanyInfo(name, phoneNum, grade);
}
public void searchData() {
System.out.print("데이터 검색을 시작합니다.\n 검색할 이름 : ");
String name = PhoneBook.sc.nextLine();
int index = nameIndex(name);
// 입력받은 이름을 nameIndex 메소드에서 처리하여 위치 번호를 받음
if (index < cnt) { //찾은 값이 주소록(phoneList)에 저장되어 있다면 값을 출력
phoneList[index].showPhoneInfo();
} else {
System.out.println("데이터를 찾을 수 없습니다.");
}
}
// searchData와 deleteData 메소드에서 공통으로 이름을 찾을 때 사용할 메소드
int nameIndex(String name) {
int index = cnt + 1;
// index가 0부터 시작하면, 맞는 데이터 값을 찾지 못해도 0을 출력하므로 범위 밖의 값을 지정함
for (int i = 0; i < cnt; i++) { // phoneList 0번째부터 이름 일치여부 확인
if (name.equals(phoneList[i].getName())) {
index = i;
}
}
return index;
}
public void deleteData() {
System.out.println("데이터 삭제를 시작합니다.\n 삭제할 이름 : ");
String name = PhoneBook.sc.nextLine();
int index = nameIndex(name);
if(index<cnt) {
arrSort(index);
System.out.println("데이터 삭제가 완료되었습니다.");
cnt--;
System.out.println("현재 남아있는 데이터의 개수는 " + cnt + "개 입니다.");
} else {
System.out.println("데이터를 찾을 수 없습니다.");
}
}
// deleteData 에서 데이터를 삭제하고 정렬하는 작업을 처리할 메소드
private void arrSort(int index) {
for (int i = index; i < cnt; i++) { //i=0부터가 아니라 index부터 유의!
phoneList[i] = phoneList[i + 1];
// 배열에서 그 뒤 인덱스 자료를 한 칸 씩 앞에다 넣어줌으로써 자리를 메꿈
// ex입력한 이름이 4번째열에 있었다면 1,2,3열은 그대로,
// 5,6,7,~ 열은 한칸씩 앞인 4,5,6,~열로 오면서 4열은 자연스럽게 덮어씌워짐
phoneList[cnt] = null;
// 한 칸 씩 앞으로 오면 마지막 열과 그 바로 앞 열이 값이 똑같기 때문에
//마지막 열의 값을 없애줘야함
}
}
public void printAllData() {
System.out.println("전체 데이터를 출력합니다.");
System.out.println("현재 저장된 데이터의 개수는 "+cnt+"개 입니다.");
for (int i = 0; i < cnt; i++) {
System.out.println("--------------------------");
phoneList[i].showPhoneInfo();
}
System.out.println("--------------------------");
}
}
입력을 받는 readData, 검색을 제공하는 searchData, 데이터를 삭제하는 deletaData, 전체출력하는 printAllData 메소드가 있으며,
readData 에서 일반 주소록인지 대학 또는 회사 주소록인지를 구분하여 저장할 수 있게 해주는 readPhoneBook, readUnivBook, readCompanyBook 메소드,
searchData와 deleteData에서 입력된 이름의 열을 저장된 주소록에서 찾아내는 nameIndex 메소드,
deleteData에서 찾아낸 삭제할 이름의 열을 삭제 및 정렬하는 arrSort 메소드가 있다.
printAllData에서 자식 클래스에서 showPhoneInfo 메소드를 오버라이딩했으므로, 자식에서 오버라이딩한 메소드가 우선 작동한다.
import java.util.Scanner;
public class PhoneBook {
static Scanner sc = new Scanner(System.in); //다른 클래스와 Scanner 공유
public static void main(String[] args) {
//PhoneBookManager 인스턴스 생성자를 호출함 (매니저 메소드를 사용하기 위해)
PhoneBookManager manager = new PhoneBookManager();
int ch;
while (true) {
showMenu();
ch = sc.nextInt();
sc.nextLine(); //이후 nextLine 쓸 때 오류 방지를 하기 위해 미리 한 칸 띄워줌
switch (ch) {
case 1:
manager.readData();
break;
case 2:
manager.searchData();
break;
case 3:
manager.deleteData();
break;
case 4:
manager.printAllData();
break;
case 5:
System.out.println("프로그램을 종료합니다.");
sc.close();
System.exit(0);
}
}
}
static void showMenu() {
System.out.println("메뉴를 선택하세요.");
System.out.println("----------------");
System.out.println("1.데이터 입력");
System.out.println("2.데이터 검색");
System.out.println("3.데이터 삭제");
System.out.println("4.데이터 전체출력");
System.out.println("5.프로그램 종료");
System.out.println("----------------");
}
}
메인 클래스이다.
이전과 같이 switch case 문을 이용하여 번호를 입력받을 수 있도록 했다.
처음 코드를 짤 때는 자식 클래스에서 부모 클래스의 메소드(showPhoneInfo)를 오버라이딩 하지 않고. 각기 다른 코드를 짰었다. (showUnivInfo, showCompanyInfo ...)
그렇게 코드를 짜게 되면 전체출력하는 printAllData 메소드에서 if문으로 instanceof 를 확인해서 회사인지, 대학인지, 일반인지를 가려내서 출력해야 했었는데, 오버라이딩을 활용하고 나니 훨씬 코드가 간결해졌다.
상속과 오버라이딩에 대한 이해를 높이고 충분히 활용할 수 있도록 연습해봐야겠다.
'개발입문 > JAVA 세미프로젝트' 카테고리의 다른 글
[JAVA] 콘솔용 POS 프로그램 만들기 (0) | 2022.10.12 |
---|---|
[JAVA] Stream을 이용하여 파일 저장이 가능한 전화번호부 만들기 (0) | 2022.10.12 |
[JAVA] HashSet을 이용하여 중복값 저장이 안 되는 전화번호부 만들기 (0) | 2022.10.12 |
[JAVA] 배열을 이용한 전화번호부 만들기 (0) | 2022.10.12 |
댓글