본문 바로가기
개발입문/JAVA 세미프로젝트

[JAVA] 상속과 오버라이딩을 이용하여 카테고리가 있는 전화번호부 만들기

by 양히◡̈ 2022. 10. 12.

오버로딩과 오버라이딩, 다형성에 대해 학습하고 응용 문제를 풀어 보았다.

이전에 작업했던 전화번호부 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 를 확인해서 회사인지, 대학인지, 일반인지를 가려내서 출력해야 했었는데, 오버라이딩을 활용하고 나니 훨씬 코드가 간결해졌다.

상속과 오버라이딩에 대한 이해를 높이고 충분히 활용할 수 있도록 연습해봐야겠다.

댓글