프로그래밍/자바(java) 융합개발자 2차

[자바 6일차] 25일차 - 다차원 배열, 상속(Do it 공부단 p.219~)

aSpring 2021. 1. 20. 08:53
728x90
728x90

2021/01/12 - [공부/자바(java) 융합개발자 2차] - [자바 1일차] 20일차 일지 - Eclipse에서 Hello 출력, 변수, if문

2021/01/13 - [공부/자바(java) 융합개발자 2차] - [자바 2일차] 21일차 - 반복문(for, while, do ~ while)

2021/01/14 - [공부/자바(java) 융합개발자 2차] - [자바 3일차] 22일차 - 배열, 난수

2021/01/14 - [공부/자바(java) 융합개발자 2차] - [자바 3일차 2] 22일차 2 - 클래스, 객체

2021/01/15 - [공부/자바(java) 융합개발자 2차] - [자바 4일차] 23일차 - 클래스

2021/01/18 - [공부/자바(java) 융합개발자 2차] - [자바 5일차] 24일 - ArrayList

 

 


1/19일자 학습 내용


 

지난 시간 복습

패키지 생성 com.day06

Drink.java 클래스 생성

- 이름, 가격만 있음

package com.day06;

public class Drink {
	private String name;
	private int price;
}

 

DrinkMain.java -> 배열 이용

==> main 작성하기

1. 판매 직원 dm 만들기

2. dm이 하는 일 - 음료 판매(inputData), 판매 리스트 보기(viewData) 만들기

==> 오류 없애주기

==> 입력 받을 수 있도록 하기

package com.day06;

import java.util.Scanner;

//배열 이용
public class DrinkMain {
	// 총 5개의 음료(이름, 가격) 입력 받기
	Scanner sc = new Scanner(System.in);
	// arr이라는 배열에 입력받은 이름, 가격 저장
	public void inputData() {
		
	}
	
	// 입고된 음료의 이름, 가격 출력
	// + 입고된 음료의 총 금액 출력
	public void viewData() {
		
	}

	
	public static void main(String[] args) { //main, 실행부
		//판매 직원 dm은 음료를 판매(inputData)하고 판매 리스트를 본다(viewData)
		DrinkMain dm = new DrinkMain(); //판매 직원 dm님 만들기
		dm.inputData(); //음료 판매
		dm.viewData(); //판매 리스트
	}
}

==> 입력받은 음료 이름, 가격을 저장할 arr 배열 만들기

==> inputData() 작성하기

1. 이름, 가격 입력받기

 

2. 입력 받은 이름, 가격을 배열 arr[0]~arr[4]에 저장하기

3. 오류 해결하기 -> Drink(인자1, 인자2) 존재하지 않음

==> viewData() 작성하기

1. 입고된 음료의 이름, 가격, 총 금액 출력

==> DrinkMain.java 전체 코드

1.

package com.day06;

import java.util.Scanner;

//배열 이용
public class DrinkMain {
	// 총 5개의 음료(이름, 가격) 입력 받기
	Scanner sc = new Scanner(System.in);
	// arr이라는 배열에 입력받은 이름, 가격 저장
	private Drink[] arr = new Drink[5]; //길이가 5인 배열 만듦
	
	public void inputData() { //이름, 가격 입력받고 arr[0]~arr[4]에 이름, 가격 저장하기
		for(int i = 0; i < arr.length; i++) { //5개 입력 받아야 하니까 배열 길이만큼 돌리기
			System.out.println("음료 이름, 가격 입력 >>");
			String name = sc.next(); //입력된 이름을 String name에 저장
			int price = sc.nextInt(); //입력된 가격을 int price에 저장
			arr[i] = new Drink(name, price);
		}
		System.out.println();
	}
	
	// 입고된 음료의 이름, 가격 출력
	// + 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		System.out.println("음료 리스트.. "); //저장된 이름, 가격 불러오기
		for(Drink d : arr) { //d.getName()이렇게 불러오려면 필요함, arr 길이 5 만큼 돌림
			System.out.println("음료 이름 : " + d.getName() + ", 가격 : " + d.getPrice());
			
			sum += d.getPrice();
		}
		System.out.println("총 금액 : " + sum);
	}
	
	public static void main(String[] args) { //main, 실행부
		//판매 직원 dm은 음료를 판매(inputData)하고 판매 리스트를 본다(viewData)
		DrinkMain dm = new DrinkMain(); //판매 직원 dm님 만들기
		dm.inputData(); //음료 판매
		dm.viewData(); //판매 리스트
	}
}

음료 이름, 가격 입력 >>
쌍화탕 1200
음료 이름, 가격 입력 >>
생수 850
음료 이름, 가격 입력 >>
포카리스웨트 1200
음료 이름, 가격 입력 >>
바나나우유 1200
음료 이름, 가격 입력 >>
요구르트 800

음료 리스트.. 
음료 이름 : 쌍화탕, 가격 : 1200
음료 이름 : 생수, 가격 : 850
음료 이름 : 포카리스웨트, 가격 : 1200
음료 이름 : 바나나우유, 가격 : 1200
음료 이름 : 요구르트, 가격 : 800
총 금액 : 5250

 

sc.next(); 사용 시

sc.next(); 사용 시 스페이스바 또는 Enter로 구분하게 되어서

포카리 스웨트 처럼 이름 사이에 스페이스바가 있으면 '포카리'를 이름으로, '스웨트'를 가격으로 받게 된다

-> sc.nextLine(); 사용

처음 입력한 한 줄 '포카리 스웨트'를 name으로 받고

두 번째 입력한 한 줄 '1200'을 price로 받는다

입력이 끝나면 sc.nextLine();으로 알려줘야 한다.

 

DrinkMain.java 전체 코드

package com.day06;

import java.util.Scanner;

//배열 이용
public class DrinkMain {
	// 총 5개의 음료(이름, 가격) 입력 받기
	Scanner sc = new Scanner(System.in);
	// arr이라는 배열에 입력받은 이름, 가격 저장
	private Drink[] arr = new Drink[5]; //길이가 5인 배열 만듦
	
	public void inputData() { //이름, 가격 입력받고 arr[0]~arr[4]에 이름, 가격 저장하기
		for(int i = 0; i < arr.length; i++) { //5개 입력 받아야 하니까 배열 길이만큼 돌리기
			System.out.println("음료 이름 >>");
			String name = sc.nextLine(); //sc.next(); 문자열을 받는 것, sc.nextLine(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받는다
			System.out.println("가격 입력 >>");
			int price = sc.nextInt(); //입력된 가격을 int price에 저장
			sc.nextLine(); //입력 끝나면 이걸 적어주어야 함
			arr[i] = new Drink(name, price);
		}
		System.out.println();
	}
	
	// 입고된 음료의 이름, 가격 출력
	// + 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		System.out.println("음료 리스트.. "); //저장된 이름, 가격 불러오기
		for(Drink d : arr) { //d.getName()이렇게 불러오려면 필요함, arr 길이 5 만큼 돌림
			System.out.println("음료 이름 : " + d.getName() + ", 가격 : " + d.getPrice());
			
			sum += d.getPrice();
		}
		System.out.println("총 금액 : " + sum);
	}
	
	public static void main(String[] args) { //main, 실행부
		//판매 직원 dm은 음료를 판매(inputData)하고 판매 리스트를 본다(viewData)
		DrinkMain dm = new DrinkMain(); //판매 직원 dm님 만들기
		dm.inputData(); //음료 판매
		dm.viewData(); //판매 리스트
	}
}

음료 이름 >>
쌍화탕
가격 입력 >>
1200
음료 이름 >>
생수
가격 입력 >>
850
음료 이름 >>
포카리 스웨트
가격 입력 >>
1200
음료 이름 >>
바나나 우유
가격 입력 >>
1200
음료 이름 >>
요구르트
가격 입력 >>
800

음료 리스트.. 
음료 이름 : 쌍화탕, 가격 : 1200
음료 이름 : 생수, 가격 : 850
음료 이름 : 포카리 스웨트, 가격 : 1200
음료 이름 : 바나나 우유, 가격 : 1200
음료 이름 : 요구르트, 가격 : 800
총 금액 : 5250

 

또는 for(Drink d : arr) 대신 int i로 for문 돌리기

package com.day06;

import java.util.Scanner;

//배열 이용
public class DrinkMain {
	Scanner sc = new Scanner(System.in);
	// 총 5개의 음료(이름, 가격) 받기
	//arr이라는 배열에 저장
	private Drink[] arr = new Drink[5];

	public void inputData() { // 입력
		for (int i = 0; i < arr.length; i++) {
			System.out.println("음료 이름 >> ");
			String name = sc.nextLine(); //sc.next(); 문자열을 받는 것, sc.nextline(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받음
			System.out.println("음료 가격 >> ");
			int price = sc.nextInt();
			sc.nextLine();
			arr[i] = new Drink(name, price);
		}
	}

	// 입고된 음료 이름, 가격 출력
	// 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		for(int i=0; i<arr.length; i++) {
			sum += arr[i].getPrice();
		}
		System.out.println("총 금액 : " + sum);
	}

	public static void main(String[] args) {
		DrinkMain dm = new DrinkMain();
		dm.inputData(); // 음료 판매
		dm.viewData(); // 판매 리스트
	}
}

결과 동일

 

Drink.java 전체 코드

package com.day06;

public class Drink { //이름, 가격 -> 멤버 변수
	private String name;
	int price;
	
	public Drink(String name, int price) {
		this.name = name;
		this.price = price;
	}
	
	//getter 만들어주기
	public String getName() { //DrinkMain에서 getName()으로 요청하면 
		return name; //저장된 name을 알려줌
	}
	public int getPrice() {
		return price;
	}
}

 

==> ArrayList로 바꿔보기

DrinkMain2.java

package com.day06;

import java.util.ArrayList;
import java.util.Scanner;

//ArrayList 이용
public class DrinkMain2 {
	Scanner sc = new Scanner(System.in);
	ArrayList<Drink> alist = new ArrayList<>();

	public void inputData() { // 입력
		for (int i=0; i<5; i++) { //alist size가 지금 0이라서 안돔.. -> alist.size()말고 5를 넣거나 while(alist.size() <5) 하거나
			System.out.println("음료 이름 >> ");
			String name = sc.nextLine(); // sc.next(); 문자열을 받는 것, sc.nextline(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받음
			System.out.println("음료 가격 >> ");
			int price = sc.nextInt();
			sc.nextLine();
			alist.add(new Drink(name, price));
		}
	}

	// 입고된 음료 이름, 가격 출력
	// 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		for (Drink d : alist) {
			System.out.println("이름 : " + d.getName());
			System.out.println("가격 : " + d.getPrice());
			System.out.println();

			sum += d.getPrice();
		}
		System.out.println("총 금액 : " + sum);
		
		int hap = 0;
		for(int i=0; i<alist.size();i++) {
			System.out.println("이름 : " + alist.get(i).getName());
			System.out.println("가격 : " + alist.get(i).getPrice());
			System.out.println();
			
			hap += alist.get(i).getPrice();
		}
		System.out.println("총 금액 : " + hap);
	}

	public static void main(String[] args) {
		DrinkMain2 dm = new DrinkMain2();
		dm.inputData(); // 음료 판매
		dm.viewData(); // 판매 리스트
	}
}

 

다시 DrinkMain.java로 와서

==> 손님이 와서 찾는 음료를 이야기 한다. 

1. 직원 dm은 음료 리스트에서 손님이 찾는 음료를 검색(search)한다

-> 오류 해결하기

 

2. 찾는 음료가 리스트에 있으면 해당 음료의 가격을 반환해주고, 찾는 음료가 리스트에 없으면 0 반환해 출력한다.

왜 없다고 0이 출력되는거지?

입력된 내용이 같은 것을 찾때는 아래처럼 적어주어야 한다

if(d.getName == searchName) 은 주소가 같은가를 물어보는 것이고

찾는 음료 searrchName에 입력한 "알로에 주스"가 배열에 저장된 '내용' 중에 같은게 있는가를 물어볼 때는 equals를 사용해야 한다.

 

package com.day06;

import java.util.Scanner;

//배열 이용
public class DrinkMain {
	// 총 5개의 음료(이름, 가격) 입력 받기
	Scanner sc = new Scanner(System.in);
	// arr이라는 배열에 입력받은 이름, 가격 저장
	private Drink[] arr = new Drink[5]; //길이가 5인 배열 만듦
	
	public void inputData() { //이름, 가격 입력받고 arr[0]~arr[4]에 이름, 가격 저장하기
		for(int i = 0; i < arr.length; i++) { //5개 입력 받아야 하니까 배열 길이만큼 돌리기
			System.out.println("음료 이름, 가격 입력 >>");
			String name = sc.nextLine(); //sc.next(); 문자열을 받는 것, sc.nextLine(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받는다
			int price = sc.nextInt(); //입력된 가격을 int price에 저장
			sc.nextLine();
			arr[i] = new Drink(name, price);
		}
		System.out.println();
	}
	
	// 입고된 음료의 이름, 가격 출력
	// + 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		System.out.println("음료 리스트.. "); //저장된 이름, 가격 불러오기
		for(int i = 0; i < arr.length; i++) { //arr 길이 5 만큼 돌림
			System.out.println("음료 이름 : " + arr[i].getName() + ", 가격 : " + arr[i].getPrice());
			
			sum += arr[i].getPrice();
		}
		System.out.println("총 금액 : " + sum);
		System.out.println();
	}
	
	//음료 찾기
	public int search() { //찾는 음료가 있으면 해당 음료의 가격 반환, 없으면 0원 반환
		System.out.println("찾으시는 음료를 입력하세요 >> "); //찾는 음료 이름을 입력하라고 말하기
		String searchName = sc.nextLine(); //찾는 음료 이름을 searchName에 입력받기 -> 나는 포카리 스웨트 처럼 공백이 있는 음료일 수도 있으니 nextline();사용
		for(Drink d : arr) { //seachName에 입력받은 음료 이름이 앞에서 내가 입고한 음료(arr[0]~arr[4] 배열에 저장) 중에 있는지 확인 
			if(searchName.equals(d.getName())) { //찾는 음료가 목록에 있으면
				return d.getPrice(); //해당 음료의 가격 반환
			}//if 종료
		}//for 종료
		return 0; //없으면 0 반환
	}//search 종료
	
	public static void main(String[] args) { //main, 실행부
		//판매 직원 dm은 음료를 입고(inputData)하고 입고된 음료 리스트를 본다(viewData)
		DrinkMain dm = new DrinkMain(); //판매 직원 dm님 만들기
		dm.inputData(); //음료 입고
		dm.viewData(); //입고된 음료 리스트
		System.out.println("찾는 음료 >> " + dm.search()); //음료 입고 완료 -> 입고된 음료 리스트 확인 -> 손님이 와서 음료 찾음 : dm.saerch() 실행
	}
}

음료 이름, 가격 입력 >>
포카리 스웨트
1500
음료 이름, 가격 입력 >>
사과 주스
1800
음료 이름, 가격 입력 >>
커피
500
음료 이름, 가격 입력 >>
아메리카노
1500
음료 이름, 가격 입력 >>
알로에 주스
2000

음료 리스트.. 
음료 이름 : 포카리 스웨트, 가격 : 1500
음료 이름 : 사과 주스, 가격 : 1800
음료 이름 : 커피, 가격 : 500
음료 이름 : 아메리카노, 가격 : 1500
음료 이름 : 알로에 주스, 가격 : 2000
총 금액 : 7300

찾으시는 음료를 입력하세요 >> 
알로에 주스
찾는 음료 >> 2000

 

==> 다른 방법으로 작성해보기

1. 오류 해결하기

2. drinkSearch() 내용 작성

package com.day06;

import java.util.Scanner;

//배열 이용
public class DrinkMain {
	// 총 5개의 음료(이름, 가격) 입력 받기
	Scanner sc = new Scanner(System.in);
	// arr이라는 배열에 입력받은 이름, 가격 저장
	private Drink[] arr = new Drink[5]; //길이가 5인 배열 만듦
	
	public void inputData() { //이름, 가격 입력받고 arr[0]~arr[4]에 이름, 가격 저장하기
		for(int i = 0; i < arr.length; i++) { //5개 입력 받아야 하니까 배열 길이만큼 돌리기
			System.out.println("음료 이름, 가격 입력 >>");
			String name = sc.nextLine(); //sc.next(); 문자열을 받는 것, sc.nextLine(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받는다
			int price = sc.nextInt(); //입력된 가격을 int price에 저장
			sc.nextLine();
			arr[i] = new Drink(name, price);
		}
		System.out.println();
	}
	
	// 입고된 음료의 이름, 가격 출력
	// + 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		System.out.println("음료 리스트.. "); //저장된 이름, 가격 불러오기
		for(Drink d : arr) { //arr 길이 5 만큼 돌림
			System.out.println("음료 이름 : " + d.getName() + ", 가격 : " + d.getPrice());
			
			sum += d.getPrice();
		}
		System.out.println("총 금액 : " + sum);
		System.out.println();
	}
	
	//음료 찾기
	public int search() { //찾는 음료가 있으면 해당 음료의 가격 반환, 없으면 0원 반환
		System.out.println("찾으시는 음료를 입력하세요 >> "); //찾는 음료 이름을 입력하라고 말하기
		String searchName = sc.nextLine(); //찾는 음료 이름을 searchName에 입력받기 -> 나는 포카리 스웨트 처럼 공백이 있는 음료일 수도 있으니 nextline();사용
		for(Drink d : arr) { //seachName에 입력받은 음료 이름이 앞에서 내가 입고한 음료(arr[0]~arr[4] 배열에 저장) 중에 있는지 확인 
			if(searchName.equals(d.getName())) { //찾는 음료가 목록에 있으면
				return d.getPrice(); //해당 음료의 가격 반환
			}//if 종료
		}//for 종료
		return 0; //없으면 0 반환
	}//search 종료
	
	public Drink drinkSearch() {
		System.out.println("찾으시는 음료를 입력하세요 >> "); //찾는 음료 이름을 입력하라고 말하기
		String sName = sc.nextLine(); //찾는 음료 이름을 sName에 입력받기
		for(int i = 0; i < arr.length; i++) {
			if(sName.equals(arr[i].getName())) { //내가 찾는 Drink의 이름이 배열에 존재하면
				return arr[i];// 해당 arr[]을 return하는데 배열 arr[]은 Drink형
			}
		}
		return null; //없으면 return값은 null
	}
	
	public static void main(String[] args) { //main, 실행부
		//판매 직원 dm은 음료를 입고(inputData)하고 입고된 음료 리스트를 본다(viewData)
		DrinkMain dm = new DrinkMain(); //판매 직원 dm님 만들기
		dm.inputData(); //음료 입고
		dm.viewData(); //입고된 음료 리스트
		System.out.println("찾는 음료 >> " + dm.search()); //음료 입고 완료 -> 입고된 음료 리스트 확인 -> 손님이 와서 음료 찾음 : dm.saerch() 실행
		Drink d = dm.drinkSearch(); //Drink d에 drinkSearch한 결과 return 값 arr[i] 또는 null 저장 -> 이렇게 찾을 수도 있다.
		if(d == null) { //return값이 null이면 -> 찾는 음료가 없다는 뜻
			System.out.println("search prcie : 찾는 음료 없음");
		} else { //return값이 null이 아니면 찾는 음료가 있다는 뜻이므로 d에는 해당 arr[i]을 return받아왔을 것 -> 해당하는 가격 출력
			System.out.println("search prcie : " + d.getPrice());
		}
	}
}

 

음료 이름, 가격 입력 >>
포카리 스웨트
1500
음료 이름, 가격 입력 >>
사과 주스
18000
음료 이름, 가격 입력 >>
커피
500
음료 이름, 가격 입력 >>
아메리카노
1500
음료 이름, 가격 입력 >>
알로에 주스
2000

음료 리스트.. 
음료 이름 : 포카리 스웨트, 가격 : 1500
음료 이름 : 사과 주스, 가격 : 18000
음료 이름 : 커피, 가격 : 500
음료 이름 : 아메리카노, 가격 : 1500
음료 이름 : 알로에 주스, 가격 : 2000
총 금액 : 23500

찾으시는 음료를 입력하세요 >> 
알로에 주스
찾는 음료 >> 2000
찾으시는 음료를 입력하세요 >> 
알로에 주스
search prcie : 2000

 

==> if 삼항연산자 사용하기

 

package com.day06;

import java.util.Scanner;

//배열 이용
public class DrinkMain {
	Scanner sc = new Scanner(System.in);
	// 총 5개의 음료(이름, 가격) 받기
	// arr이라는 배열에 저장
	private Drink[] arr = new Drink[3]; //너무 많으니까 3으로 줄임

	public void inputData() { // 입력
		for (int i = 0; i < arr.length; i++) {
			System.out.println("음료 이름 >> ");
			String name = sc.nextLine(); // sc.next(); 문자열을 받는 것, sc.nextline(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받음
			System.out.println("음료 가격 >> ");
			int price = sc.nextInt();
			sc.nextLine();
			arr[i] = new Drink(name, price);
		}
	}

	// 입고된 음료 이름, 가격 출력
	// 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		for (Drink d : arr) {
			System.out.println("이름 : " + d.getName());
			System.out.println("가격 : " + d.getPrice());
			System.out.println();

			sum += d.getPrice();
		}
		System.out.println("총 금액 : " + sum);
	}
	
	public int search() {
		System.out.println("찾는 음료 이름 >> ");
		String searchName = sc.next();
		for(int i = 0; i < arr.length; i++) {
			if(searchName.equals(arr[i].getName())) { //내용이 같은지
				return arr[i].getPrice(); //손님이 찾는 음료가 배열에 있으면 가격 출력
			}
		}
		return 0; //손님이 찾는 음료가 배열에 없으면 0 출력
	}
	
	public Drink drinkSearch() {
		System.out.println("찾는 음료 이름 >> ");
		String sname = sc.next();
		for(int i = 0; i < arr.length; i++) {
			if(sname.equals(arr[i].getName())) { //내가 찾는 Drink
				return arr[i]; //arr[i]가 Drink형임
			}
		}
		return null;
	}

	public static void main(String[] args) {
		DrinkMain dm = new DrinkMain();
		dm.inputData(); // 음료 판매
		dm.viewData(); // 판매 리스트
		System.out.println("찾는 음료 가격 >> " + dm.search()); //손님이 와서 음료를 찾음
		Drink d = dm.drinkSearch(); //return형은 Drink -> 이렇게 찾을 수도 있다.
		if(d == null) {
			System.out.println(" search price : 찾는 음료 없음");
		} else {
			System.out.println(" search price : " + d.getPrice()); //찾는 음료가 있으면 가격을 알려 줌
		}
		//삼항연산자
		System.out.println(" search price : " + ((d==null) ? "0" : d.getPrice()));
		
	}
}

음료 이름 >> 
aaa
음료 가격 >> 
111
음료 이름 >> 
bbb
음료 가격 >> 
222
음료 이름 >> 
ccc
음료 가격 >> 
333
이름 : aaa
가격 : 111

이름 : bbb
가격 : 222

이름 : ccc
가격 : 333

총 금액 : 666
찾는 음료 이름 >> 
ddd
찾는 음료 가격 >> 0
찾는 음료 이름 >> 
ddd
 search price : 찾는 음료 없음
 search price : 0

 

헷갈리니까 표현 조금 다르게 함

package com.day06;

import java.util.Scanner;

//배열 이용
public class DrinkMain {
	Scanner sc = new Scanner(System.in);
	// 총 5개의 음료(이름, 가격) 받기
	// arr이라는 배열에 저장
	private Drink[] arr = new Drink[3]; //너무 많으니까 3으로 줄임

	public void inputData() { // 입력
		for (int i = 0; i < arr.length; i++) {
			System.out.println("음료 이름 >> ");
			String name = sc.nextLine(); // sc.next(); 문자열을 받는 것, sc.nextline(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받음
			System.out.println("음료 가격 >> ");
			int price = sc.nextInt();
			sc.nextLine();
			arr[i] = new Drink(name, price);
		}
	}

	// 입고된 음료 이름, 가격 출력
	// 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		for (Drink d : arr) {
			System.out.println("이름 : " + d.getName());
			System.out.println("가격 : " + d.getPrice());
			System.out.println();

			sum += d.getPrice();
		}
		System.out.println("총 금액 : " + sum);
	}
	
	public int search() {
		System.out.println("search 찾는 음료 이름 >> ");
		String searchName = sc.next();
		for(int i = 0; i < arr.length; i++) {
			if(searchName.equals(arr[i].getName())) { //내용이 같은지
				return arr[i].getPrice(); //손님이 찾는 음료가 배열에 있으면 가격 출력
			}
		}
		return 0; //손님이 찾는 음료가 배열에 없으면 0 출력
	}
	
	public Drink drinkSearch() {
		System.out.println("찾는 음료 이름 >> ");
		String sname = sc.next();
		for(int i = 0; i < arr.length; i++) {
			if(sname.equals(arr[i].getName())) { //내가 찾는 Drink
				return arr[i]; //arr[i]가 Drink형임
			}
		}
		return null;
	}

	public static void main(String[] args) {
		DrinkMain dm = new DrinkMain();
		dm.inputData(); // 음료 판매
		dm.viewData(); // 판매 리스트
		System.out.println("찾는 음료 가격 >> " + dm.search()); //손님이 와서 음료를 찾음
		Drink d = dm.drinkSearch(); //return형은 Drink -> 이렇게 찾을 수도 있다.
		if(d == null) {
			System.out.println(" search price : 찾는 음료 없음");
		} else {
			System.out.println(" search price : " + d.getPrice()); //찾는 음료가 있으면 가격을 알려 줌
		}
		//삼항연산자
		System.out.println(" search price : " + ((d==null) ? "0" : d.getPrice()));
		
	}
}

음료 이름 >> 
aaa
음료 가격 >> 
111
음료 이름 >> 
bbb
음료 가격 >> 
222
음료 이름 >> 
ccc
음료 가격 >> 
333
이름 : aaa
가격 : 111

이름 : bbb
가격 : 222

이름 : ccc
가격 : 333

총 금액 : 666
search 찾는 음료 이름 >> 
ddd
찾는 음료 가격 >> 0 -> 이렇게 찾아도 되고


찾는 음료 이름 >> 
ddd
 search price : 찾는 음료 없음
 search price : 0 -> 이렇게 찾아도 됨

 

 

==> DrinkMain2.java에 아래 부분만 복사해서 붙여넣기

System.out.println("찾는 음료 가격 >> " + dm.search()); //손님이 와서 음료를 찾음
		Drink d = dm.drinkSearch(); //return형은 Drink -> 이렇게 찾을 수도 있다.
		if(d == null) {
			System.out.println(" search price : 찾는 음료 없음");
		} else {
			System.out.println(" search price : " + d.getPrice()); //찾는 음료가 있으면 가격을 알려 줌
		}
		//삼항연산자
		System.out.println(" search price : " + ((d==null) ? "0" : d.getPrice()));

==>

package com.day06;

import java.util.ArrayList;
import java.util.Scanner;

//ArrayList 이용
public class DrinkMain2 {
	Scanner sc = new Scanner(System.in);
	ArrayList<Drink> alist = new ArrayList<>();

	public void inputData() { // 입력
		for (int i=0; i<5; i++) { //alist size가 지금 0이라서 안돔.. -> alist.size()말고 5를 넣거나 while(alist.size() <5) 하거나
			System.out.println("음료 이름 >> ");
			String name = sc.nextLine(); // sc.next(); 문자열을 받는 것, sc.nextline(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받음
			System.out.println("음료 가격 >> ");
			int price = sc.nextInt();
			sc.nextLine();
			alist.add(new Drink(name, price));
		}
	}

	// 입고된 음료 이름, 가격 출력
	// 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		for (Drink d : alist) {
			System.out.println("이름 : " + d.getName());
			System.out.println("가격 : " + d.getPrice());
			System.out.println();

			sum += d.getPrice();
		}
		System.out.println("총 금액 : " + sum);
		
		int hap = 0;
		for(int i=0; i<alist.size();i++) {
			System.out.println("이름 : " + alist.get(i).getName());
			System.out.println("가격 : " + alist.get(i).getPrice());
			System.out.println();
			
			hap += alist.get(i).getPrice();
		}
		System.out.println("총 금액 : " + hap);
	}

	public static void main(String[] args) {
		DrinkMain2 dm = new DrinkMain2();
		dm.inputData(); // 음료 판매
		dm.viewData(); // 판매 리스트
		System.out.println("찾는 음료 가격 >> " + dm.search()); //손님이 와서 음료를 찾음
		Drink d = dm.drinkSearch(); //return형은 Drink -> 이렇게 찾을 수도 있다.
		if(d == null) {
			System.out.println(" search price : 찾는 음료 없음");
		} else {
			System.out.println(" search price : " + d.getPrice()); //찾는 음료가 있으면 가격을 알려 줌
		}
		//삼항연산자
		System.out.println(" search price : " + ((d==null) ? "0" : d.getPrice()));
	}
}

==> 오류 없애주기

==> 전체 DrinkMain2.java 코드 채우기

inputData를 먼저 해주어야 하는데 alist.size()만큼 돌리면 inputData 실행되지 않음 -> alist.size()는 입고 전이므로 길이가 0이라서!

따라서 입력받을 만큼인 5로 for문 돌리는 조건 수정 해주기

 

package com.day06;

import java.util.ArrayList;
import java.util.Scanner;

//ArrayList 이용
public class DrinkMain2 {
	Scanner sc = new Scanner(System.in);
	ArrayList<Drink> alist = new ArrayList<>();

	public void inputData() { // 입력
		for (int i=0; i<5; i++) { //alist size가 지금 0이라서 안돔.. -> alist.size()말고 5를 넣거나 while(alist.size() <5) 하거나
			System.out.println("음료 이름 >> ");
			String name = sc.nextLine(); // sc.next(); 문자열을 받는 것, sc.nextline(); 문자열을 받는데 Enter까지 받는 것. 한 줄을 입력 받음
			System.out.println("음료 가격 >> ");
			int price = sc.nextInt();
			sc.nextLine();
			alist.add(new Drink(name, price));
		}
	}

	// 입고된 음료 이름, 가격 출력
	// 입고된 음료의 총 금액 출력
	public void viewData() {
		int sum = 0;
		for (Drink d : alist) {
			System.out.println("이름 : " + d.getName());
			System.out.println("가격 : " + d.getPrice());
			System.out.println();

			sum += d.getPrice();
		}
		System.out.println("총 금액 : " + sum);
		
		int hap = 0;
		for(int i=0; i<alist.size();i++) {
			System.out.println("이름 : " + alist.get(i).getName());
			System.out.println("가격 : " + alist.get(i).getPrice());
			System.out.println();
			
			hap += alist.get(i).getPrice();
		}
		System.out.println("총 금액 : " + hap);
	}
	
	public int search() { //private는 경우에 따라 써줘도 되고 안써줘도 됨
		System.out.println("search 찾는 음료 이름 : ");
		String searchName = sc.next();
		for(int i=0; i < alist.size(); i++) { //각각 search 해야 해서 for-each문을 쓸 수는 없다
			if(searchName.equals(alist.get(i).getName())) { //내용 비교 시 equals 사용
				return alist.get(i).getPrice();
			}
		}
		return 0; //없으면 가격 0 반환
	}
	
	public Drink drinkSearch() {
		System.out.println("drinkSearch 찾는 음료 이름 : ");
		String sName = sc.next(); //위랑 같은 searchName으로 해도 됨
		for(int i=0; i < alist.size(); i++) {
			if(sName.equals(alist.get(i).getName())) {
				return alist.get(i);
			}
		}
		return null; //객체니까 0 아니고 null 반환
	}

	public static void main(String[] args) {
		DrinkMain2 dm = new DrinkMain2();
		dm.inputData(); // 음료 판매
		dm.viewData(); // 판매 리스트
		System.out.println("찾는 음료 가격 >> " + dm.search()); //손님이 와서 음료를 찾음
		Drink d = dm.drinkSearch(); //return형은 Drink -> 이렇게 찾을 수도 있다.
		if(d == null) {
			System.out.println(" search price : 찾는 음료 없음");
		} else {
			System.out.println(" search price : " + d.getPrice()); //찾는 음료가 있으면 가격을 알려 줌
		}
		//삼항연산자
		System.out.println(" search price : " + ((d==null) ? "0" : d.getPrice()));
	}
}

return 값이 Drink형★

& return값은 반드시 맨 마지막에 있어야 한다

 

DrinkMain.java와 DrinkMain2.java 비교해보기

 

실행 결과는 동일하다

 

음료 이름 >> 
aaa
음료 가격 >> 
111
음료 이름 >> 
bbb
음료 가격 >> 
222
음료 이름 >> 
ccc
음료 가격 >> 
333
이름 : aaa
가격 : 111

이름 : bbb
가격 : 222

이름 : ccc
가격 : 333

총 금액 : 666
이름 : aaa
가격 : 111

이름 : bbb
가격 : 222

이름 : ccc
가격 : 333

총 금액 : 666
search 찾는 음료 이름 : 
aaa
찾는 음료 가격 >> 111
drinkSearch 찾는 음료 이름 : 
ddd
 search price : 찾는 음료 없음
 search price : 0


07-2 다차원 배열(p.219~)

d[] 1 2 3 4 5 -> 일차원 배열

 []  6 7 8 9 10         -> 이차원 배열

d[2][5] -> 배열 d의 2행 5열 : 10

 

- 이때까지는 하나의 행으로 이루어진 일차원 배열을 다뤘음

- 수학에서 x, y좌표를 쓰는 것처럼 프로그램에서도 평면을 구현하기 위해 이차원 배열 사용

ex) 바둑, 체스 게임, 네비게이션 지도 등을 구현 시 활용

- 삼차원 이상의 배열도 가능 : 주로 공간을 나타내는 프로그램에서 활용

-> 이렇게 이차원 이상으로 구현한 배열 : 다차원 배열 -> 평면이나 공간 개념 구현에 사용

 

ArrayTest.java

1. 일차원 배열 a와 b만들기

==> 주소가 아닌 내용 출력하기

==> 2차원 배열 arr만들기

==> 내용 채우기

==> 2차원 배열 출력하기

==> 이중 for문 완성하기

==> ArrayTest 전체 코드

package com.day06;

public class ArrayTest {

	public static void main(String[] args) {
		//일차원 배열 a, b 만들기
		int[] a = {1,2,3,4,5}; // 일차원 배열 a
		int[] b = {6,7,8,9,10}; // 일차원 배열 b
		
		//일차원 배열 a 출력
		for(int i = 0; i < a.length; i++) {
			System.out.print(a[i]+"\t");
		}
		System.out.println();
		System.out.println("========================");
		
		//2차원으로 만들어주기
		int[][] arr = {{1,2,3,4,5}, {6,7,8,9,10}};//2행 5열
		//2차원 배열 출력하기
		for(int i = 0; i < arr.length; i++) { //       i 0일 때(1행)       | i 1일 때(2행)
			for(int j = 0; j < arr[i].length; j++) { //1 2 3 4 5 열 출력   | 1 2 3 4 5열 출력
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println();
		}
	}
}

==> arr, arr[0], arr[1], arr[0][4], arr[1][3] 출력해보기

1. 실행 전 예측

2. 실행 : 결과값

ArrayTest.java 전체 코드

package com.day06;

public class ArrayTest {

	public static void main(String[] args) {
		//일차원 배열 a, b 만들기
		int[] a = {1,2,3,4,5}; // 일차원 배열 a
		int[] b = {6,7,8,9,10}; // 일차원 배열 b
		
		//일차원 배열 a 출력
		for(int i = 0; i < a.length; i++) {
			System.out.print(a[i]+"\t");
		}
		System.out.println();
		System.out.println("==============================================");
		
		//2차원으로 만들어주기
		int[][] arr = {{1,2,3,4,5}, {6,7,8,9,10}};//2행 5열
		//2차원 배열 출력하기
		for(int i = 0; i < arr.length; i++) { //       i 0일 때(1행)       | i 1일 때(2행)
			for(int j = 0; j < arr[i].length; j++) { //1 2 3 4 5 열 출력   | 1 2 3 4 5열 출력
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println();
		}
		System.out.println("arr : " + arr); //주소값 출력됨 : [[I@7637f22
		System.out.println("arr[0] : " + arr[0]); //주소값 출력됨 : [I@4926097b
		System.out.println("arr[1] : " + arr[1]); //주소값 출력됨 : [I@762efe5d
		System.out.println("arr[0][4] : " + arr[0][4]); //1행 5열의 값 : 5
		System.out.println("arr[1][3] : " + arr[1][3]); //2행 4열의 값 : 9
	}
}

1 2 3 4 5
==================================
1 2 3 4 5
6 7 8 9 10
arr : [[I@7637f22
arr[0] : [I@4926097b

arr[1] : [I@762efe5d
arr[0][4] : 5
arr[1][3] : 9

 

행, 열 길이만 알고 안에 내용은 모를 때

package com.day06;

public class ArrayTest {

	public static void main(String[] args) {
		//일차원 배열 a, b 만들기
		int[] a = {1,2,3,4,5}; // 일차원 배열 a
		int[] b = {6,7,8,9,10}; // 일차원 배열 b
		
		//일차원 배열 a 출력
		for(int i = 0; i < a.length; i++) {
			System.out.print(a[i]+"\t");
		}
		System.out.println();
		System.out.println("==============================================");
		
		//2차원으로 만들어주기
		int[][] arr = {{1,2,3,4,5}, {6,7,8,9,10}};//2행 5열
		//2차원 배열 출력하기
		for(int i = 0; i < arr.length; i++) { //       i 0일 때(1행)       | i 1일 때(2행)
			for(int j = 0; j < arr[i].length; j++) { //1 2 3 4 5 열 출력   | 1 2 3 4 5열 출력
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println();
		}
		System.out.println("arr : " + arr); //주소값 출력됨 : [[I@7637f22
		System.out.println("arr[0] : " + arr[0]); //주소값 출력됨 : [I@4926097b
		System.out.println("arr[1] : " + arr[1]); //주소값 출력됨 : [I@762efe5d
		System.out.println("arr[0][4] : " + arr[0][4]); //1행 5열의 값 : 5
		System.out.println("arr[1][3] : " + arr[1][3]); //2행 4열의 값 : 9
		
		//행 길이만 알고 안의 내용은 모를 때
		int[][] arr2 = new int[2][3];
	}
}

ShiftArray.java

3행 3열의 배열을 만들 것

==> 배열에 들어가는 내용을 이미 알고 있으므로 바로 넣어줄 것

==> 1열 1, 2, 3  / 2열 4, 5, 6  / 3열 7, 8, 9 바로 넣어주기

package com.day06;

public class ShiftArray {

	public static void main(String[] args) {
		int[][] arr = {{1,2,3}, {4,5,6}, {7,8,9}}; //3행, 3열

	}

}

==> 현재 배열 출력해보기

 

    [0]  [1]  [2]
[0]  1    2    3
[1]  4    5    6
[2]  7    8    9


이런 배열 상태인데

    [0]  [1]  [2] 
[0]  7   8    9 
[1]  1   2    3 
[2]  4   5    6

 

이렇게 이동시키고 싶음

==> 이동 shift 메소드

 

==> 오류 없애기

==> 내용 채우기

arr배열의 출력은 main 밖 showArray에서 하는데, 배열 arr은 main 안에서밖에 모르므로 () 안에 넣어서 전해주기

==> 헷갈리니까 arrshift말고 같은 이름 arr로 써주기

package com.day06;

public class ShiftArray {
	//이동(shift) 메소드
	public static void showArray(int[][] arr) {  //객체 만들지 않고 클래스 이름으로 바로 접근 가능하도록 static으로 선언
		for(int i = 0; i < arr.length; i++) {  //받아온 arr의 내용 출력할 수 있도록 이중 for문 돌림
			for(int j = 0; j < arr[i].length; j++) {
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println();
		}
	}
	
	public static void main(String[] args) {
		// 3행 3열의 배열 만들기
		int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
		ShiftArray.showArray(arr);//static을 써주면 객체를 만들지 않고 클래스 이름으로 접근해서 직접적으로 가능! & arr의 내용은 showArray()에서 출력해주는데 arr은 main안에서밖에 모르므로 ()안에 arr을 넣어줌
	}//main 종료
} //ShiftArray 클래스 종료

1 2 3 ==> 0행        7 8 9 넣음

4 5 6 ==> 1행        1 2 3을 넣으려면 4 5 6을 다른 곳에 보관한 뒤에 넣어야 함

7 8 9 ==> 2행        7 8 9를 보관해 두고 아까 보관해 뒀던 4 5 6을 여기에 넣음

                        보관했던 7 8 9를 0줄에 넣음

 

원하는 결과는 다음과 같음

0행 7 8 9

1행 1 2 3

2행 4 5 6

 

==> 임시 보관 장소 tmp 만들어서

1. 기존의 2행에 들어있던 값 : 7 8 9를 tmp에 임시 보관함

2. 2행에는 1행의 값 4 5 6을 넣음

3. 1행에는 0행의 값 7 8 9를 넣음

4. 0행에는 tmp에 보관되어있던 7 8 9를 넣음

--> 결과

7 8 9

1 2 3

4 5 6

이 됨!

 

==> 임시 보관 장소 tmp에는 2행만 보관할 것이므로 일차 배열로 만들어 주면 됨

tmp = {7, 8, 9} 상태

 

arr[0] 1 2 3

arr[1] 4 5 6

arr[2] 7 8 9

 

==> 2행에는 1행의 값 보관, 1행에는 0행의 값 보관해야 하니까 for문 돌리기

tmp = {7, 8, 9}

 

arr[0] 1 2 3

arr[1] 4 5 6 123

arr[2] 7 8 9 456

 

==> 0행에는 tmp에 보관했던 값 저장

tmp = {7, 8, 9}

 

arr[0] 1 2 3 7 8 9

arr[1] 4 5 6 1 2 3

arr[2] 7 8 9 4 5 6

 

==> 전체 코드

package com.day06;

public class ShiftArray {
	public static void showArray(int[][] arr) {  //객체 만들지 않고 클래스 이름으로 바로 접근 가능하도록 static으로 선언
		for(int i = 0; i < arr.length; i++) {  //받아온 arr의 내용 출력할 수 있도록 이중 for문 돌림
			for(int j = 0; j < arr[i].length; j++) {
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println();
		}
	}
	
	//이동(shift) 메소드
	public static void shiftArray(int[][] arr) { //위처럼 static으로 선언, main에서 arr의 내용을 받아와서 사용할 거니까 않게 똑같은 이름(arr)으로 해주기
		int[] tmp = arr[arr.length-1]; //arr의 길이는 3인데 2행을 tmp에 담을 거니까 arr의 길이 3 - 1 해서 arr[2]를 담을 수 있도록 함
		for(int i = arr.length-2; i >= 0 ; i--) { //arr[2]에는 arr[1]값 보관, arr[1]에는 arr[0]의 값 보관 해야 하니까 i는 감소해야 함 -> i 1 -> 0으로 변화
			arr[i+1] = arr[i];//arr[1+1] = arr[1], arr[0+1]=arr[0] 보관
		}
		arr[0] = tmp;
	}
	
	public static void main(String[] args) {
		int[][] arr = {{1,2,3},{4,5,6},{7,8,9}}; // 3행 3열의 배열 생성
		ShiftArray.showArray(arr);//static을 써주면 객체를 만들지 않고 클래스 이름으로 접근해서 직접적으로 가능! & arr의 내용은 showArray()에서 출력해주는데 arr은 main안에서밖에 모르므로 ()안에 arr을 넣어줌
	}//main 종료
} //ShiftArray 클래스 종료

==> 바뀐 배열 출력

==> 전체 코드

package com.day06;

public class ShiftArray {
	//출력 메소드
	public static void showArray(int[][] arr) {  //객체 만들지 않고 클래스 이름으로 바로 접근 가능하도록 static으로 선언
		for(int i = 0; i < arr.length; i++) {  //받아온 arr의 내용 출력할 수 있도록 이중 for문 돌림
			for(int j = 0; j < arr[i].length; j++) {
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println();
		}
	}
	
	//이동(shift) 메소드
	public static void shiftArray(int[][] arr) { //위처럼 static으로 선언, main에서 arr의 내용을 받아와서 사용할 거니까 않게 똑같은 이름(arr)으로 해주기
		int[] tmp = arr[arr.length-1]; //arr의 길이는 3인데 2행을 tmp에 담을 거니까 arr의 길이 3 - 1 해서 arr[2]를 담을 수 있도록 함
		for(int i = arr.length-2; i >= 0 ; i--) { //arr[2]에는 arr[1]값 보관, arr[1]에는 arr[0]의 값 보관 해야 하니까 i는 감소해야 함 -> i 1 -> 0으로 변화
			arr[i+1] = arr[i];//arr[1+1] = arr[1], arr[0+1]=arr[0] 보관
		}
		arr[0] = tmp;
	}
	
	public static void main(String[] args) {
		int[][] arr = {{1,2,3},{4,5,6},{7,8,9}}; // 3행 3열의 배열 생성
		ShiftArray.showArray(arr);//static을 써주면 객체를 만들지 않고 클래스 이름으로 접근해서 직접적으로 가능! & arr의 내용은 showArray()에서 출력해주는데 arr은 main안에서밖에 모르므로 ()안에 arr을 넣어줌
		System.out.println("1차 이동...");
		ShiftArray.shiftArray(arr);//배열 이동 메소드 실행
		ShiftArray.showArray(arr);//이동 후 배열 출력 메소드 실행
		
	}//main 종료
} //ShiftArray 클래스 종료

 

 


08 상속과 다형성(p.232~)

1. 상속이란?

상속(inheritance) : 객체 지향 프로그래밍의 중요한 특징 중 하나

- 부모에게 재산을 상속받으면 상속받은 재산을 자신의 것으로 사용할 수 있다.

-> B 클래스가 A 클래스를 상속받으면 B클래스는 A클래스의 멤버 변수와 메서드를 사용할 수 있다.

- 유지 보수가 편하고 프로그램을 수정하거나 새로운 내용을 추가하는 것이 유연한데, 그 기반이 되는 기술이 바로 상속

 

Father.java

package com.day06;

public class Father {
	public Father() { //생성자
		System.out.println("Father 생성자");
	}
	public void fatherMethod() { //함수
		System.out.println("FatherMethod");
	}
}

GrandFather.java

package com.day06;

public class GrandFather {
	public GrandFather() { //생성자
		System.out.println("GrandFather 생성자");
	}
	public void grandfatherMethod() { //함수
		System.out.println("grandFatherMethod");
	}
}

Main.java GrandFather와 Father에 있는 함수 실행할 수 있도록 객체 생성해줄 것임

==> GrandFather 객체 gf와 Father객체 f 생성

package com.day06;

public class Main {

	public static void main(String[] args) {
		GrandFather gf = new GrandFather();
		
		System.out.println("===================");
		
		f.fatherMethod();
	}
}

객체 생성하기만 해도 생성자 호출 -> 출력 실행함

 

==> grandfatherMethod 함수 실행

 

==> fatherMethod 함수 실행

 

==> Main.java 전체 코드

package com.day06;

public class Main {

	public static void main(String[] args) {
		GrandFather gf = new GrandFather();
		gf.grandfatherMethod();
		System.out.println("===================");
		Father f = new Father();
		f.fatherMethod();
	}
}

 

==> grandFatherMethod() 호출

 

오류 -> grandfatherMethod()함수는 Father가 아니라 GrandFather이 갖고 있는 것인데 Father의 객체 f가 접근하려고 하였으므로 에러 -> GrandFather가 갖고 있는 함수를 Father가 사용하고 싶으면 상속 받아야 함

==> 실행해보기

==>

package com.day06;

public class Main {

   public static void main(String[] args) {
      GrandFather gf=new GrandFather();
      gf.grandFatherMethod();
      System.out.println("=============");
      Father f=new Father();
      f.fatherMethod();
      
      f.grandFatherMethod(); //Father에 extends를 사용하지 않으면 오류가 나지만 extends 사용으로 오류x 상속받음?
   }
}

GrandFather 생성자
grandFatherMethod
==Father는 GrandFather을 상속받음===
GrandFather 생성자  -> 얘가 먼저 나옴 : 부모가 먼저 실행됨
Father 생성자
FatherMethod
==Father가 상속받음 함수 사용===
grandFatherMethod

 

==> extends GrandFather 를 지우면

GrandFather 생성자
grandFatherMethod
==Father가 GrandFather을 상속받기 전===
Father 생성자  --> 할아버지 나오지 않음
FatherMethod

 

cf) 상속받은 후

 

==> 코드 전체 보기

Main.java

package com.day06;

public class Main {

	public static void main(String[] args) {
		GrandFather gf = new GrandFather();
		gf.grandfatherMethod();
		
		System.out.println("==Father가 GrandFather을 상속받은 후===");
		Father f = new Father();
		f.fatherMethod();
		System.out.println("==Father가 GrandFather의 함수 사용===");
		f.grandfatherMethod();
	}
}

GrandFather.java

package com.day06;

public class GrandFather {
	public GrandFather() { //생성자
		System.out.println("GrandFather 생성자");
	}
	public void grandfatherMethod() { //함수
		System.out.println("grandFatherMethod");
	}
}

Father.java

package com.day06;

public class Father { //***extends 부모의 ~를 먼저 실행
   public Father() {
      //super(); ***super 생략가능
      System.out.println("Father 생성자");
   }

   public void fatherMethod() {
      System.out.println("fatherMethod");
   }
}

GrandFather 생성자
grandFatherMethod
==Father가 GrandFather을 상속받은 후===
GrandFather 생성자
Father 생성자
FatherMethod
==Father가 GrandFather의 함수 사용===
grandFatherMethod

 

super() : 상위 생성자를 부르는 것(부모의 생성자를 부른다.) -> 디폴트값, 생략 가능!

 

Child.java 만들기

package com.day06;

public class Child {
	public Child() { //생성자
		System.out.println("Child 생성자");
	}
	public void childMethod() { //함수
		System.out.println("childMethod");
	}
}

==> Main.java에 Child 객체 만들어줌

package com.day06;

public class Main {

	public static void main(String[] args) {
		GrandFather gf = new GrandFather();
		gf.grandfatherMethod();
		
		System.out.println("==Father가 GrandFather을 상속받은 후===");
		Father f = new Father();
		f.fatherMethod();
        
		System.out.println("==Father가 GrandFather의 함수 사용===");
		f.grandfatherMethod();
        
		System.out.println("==Child객체 생성==");
		Child c = new Child(); //자기 생성자한테 달려감
	}
}

GrandFather 생성자
grandFatherMethod
==Father가 GrandFather을 상속받은 후===
GrandFather 생성자
Father 생성자
FatherMethod
==Father가 GrandFather의 함수 사용===
grandFatherMethod
==Child객체 생성==
Child 생성자

 

==> Child.java에서 Father것 상속 받기

package com.day06;
//Father 상속
public class Child extends Father {
   public Child() {
	   //super(); -> 생략가능
      System.out.println("Child 생성자");
   }
   public void childMethod() {
      System.out.println("childMethod");
   }
}

GrandFather 생성자
grandFatherMethod
=============
GrandFather 생성자
Father 생성자
fatherMethod
grandFatherMethod
============
GrandFather 생성자
Father 생성자
Child 생성자

 

Child가 Father를 상속받게 되면 자기 자신의 생성자보다 먼저 상속해준 Father의 생성자로 달려감 -> Father는 자신에게 상속해준 GrandFather 생성자에게로 감

따라서 child의 객체를 생성 new Child(); 하자마자 Child의 부모 Father의 부모 GrandFather -> Child의 부모 Father -> 자기 자신 Child 순으로 실행됨

 

어차피 부모 Father를 상속 받으면 부모의 부모인 GrandFather 것도 받게 될텐데 어차피 이렇게 받을거면

아래처럼 한번에 받으면 안되는가?

불가능함 -> 자바는 다중 상속이 불가능함!

그러나 원칙 적으로는 불가능 하지만 부모의 부모.. 를 이용한 것처럼, 다중 상속이 가능한 것처럼 사용할 수 있음

 

==> Child의 객체 c가 부모인 Father의 함수와 부모의 부모 GrandFather의 함수를 모두 호출할 수 있다.

 

package com.day06;

public class Main {

	public static void main(String[] args) {
		GrandFather gf = new GrandFather();
		gf.grandfatherMethod();
		
		System.out.println("==Father가 GrandFather을 상속받은 후===");
		Father f = new Father();
		f.fatherMethod();
		System.out.println("==Father가 GrandFather의 함수 사용===");
		f.grandfatherMethod();
		System.out.println("==Child객체 생성==");
		Child c = new Child(); //자기 생성자한테 달려감
		System.out.println("==Child가 부모의 함수 사용===");
		c.childMethod(); //자기 자신의 함수는 당연히 사용 가능
		c.fatherMethod(); //Father를 상속 받았으므로 부모 Father의 함수 사용 가능
		c.grandfatherMethod(); //부모 Father이 GrandFather를 상속받았으므로 이 또한 사용 가능
	}
}

GrandFather 생성자
grandFatherMethod
==Father가 GrandFather을 상속받은 후===
GrandFather 생성자
Father 생성자
FatherMethod
==Father가 GrandFather의 함수 사용===
grandFatherMethod
==Child객체 생성==
GrandFather 생성자
Father 생성자
Child 생성자
==Child가 부모의 함수 사용===
childMethod
FatherMethod
grandFatherMethod

 

==> GrandFather.java

package com.day06;

public class GrandFather {
	private String value = "재산있음";
	
   public GrandFather() {
      System.out.println("GrandFather 생성자");
   }
   public void grandFatherMethod() {
      System.out.println("grandFatherMethod");
   }
}

==> Main.java에서 Child의 객체 c를 이용해 value 출력

package com.day06;

public class Main {

   public static void main(String[] args) {
      GrandFather gf=new GrandFather();
      gf.grandFatherMethod();
      System.out.println("=============");
      Father f=new Father();
      f.fatherMethod();
      
      f.grandFatherMethod(); //Father에 extends를 사용하지 않으면 오류가 나지만 extends 사용으로 오류x 상속받음?
      System.out.println("============");
      Child c=new Child();
      c.childMethod(); //자기것 사용 가능
      c.fatherMethod(); //상속 받은 아버지것 사용 가능
      c.grandFatherMethod(); //상속 받은 아버지의 아버지 -> 할아버지것 사용 가능
      System.out.println(c.value);
   }
}

Child가 상속을 받았지만 private로 선언된 value에는 접근 불가능함

 

==> 상속 받았은 자식이 사용 가능하도록 하려면 private 대신 protected를 써주기!

그러면 상속받은 자식은 사용 가능

 

GrandFather 생성자
grandFatherMethod
==Father가 GrandFather을 상속받은 후===
GrandFather 생성자
Father 생성자
FatherMethod
==Father가 GrandFather의 함수 사용===
grandFatherMethod
==Child객체 생성==
GrandFather 생성자
Father 생성자
Child 생성자
==Child가 부모의 함수 사용===
childMethod
FatherMethod
grandFatherMethod
재산있음

 

==> GrandFather.java에 method() 추가

package com.day06;

public class GrandFather {
	protected String value = "재산있음";
	
	public GrandFather() { //생성자
		System.out.println("GrandFather 생성자");
	}
	public void grandfatherMethod() { //함수
		System.out.println("grandFatherMethod");
	}
	
	public void method() {
		System.out.println("method");
	}
}

==> Child 객체 c가 method() 호출

package com.day06;

public class Main {

	public static void main(String[] args) {
		GrandFather gf = new GrandFather();
		gf.grandfatherMethod();
		
		System.out.println("==Father가 GrandFather을 상속받은 후===");
		Father f = new Father();
		f.fatherMethod();
		System.out.println("==Father가 GrandFather의 함수 사용===");
		f.grandfatherMethod();
		System.out.println("==Child객체 생성==");
		Child c = new Child(); //자기 생성자한테 달려감
		System.out.println("==Child가 부모의 함수 사용===");
		c.childMethod(); //자기 자신의 함수는 당연히 사용 가능
		c.fatherMethod(); //Father를 상속 받았으므로 부모 Father의 함수 사용 가능
		c.grandfatherMethod(); //부모 Father이 GrandFather를 상속받았으므로 이 또한 사용 가능
		System.out.println(c.value);
		c.method();// 상속 받았으므로 할아버지의 메소드 사용 가능
	}
}

GrandFather 생성자
grandFatherMethod
==Father가 GrandFather을 상속받은 후===
GrandFather 생성자
Father 생성자
FatherMethod
==Father가 GrandFather의 함수 사용===
grandFatherMethod
==Child객체 생성==
GrandFather 생성자
Father 생성자
Child 생성자
==Child가 부모의 함수 사용===
childMethod
FatherMethod
grandFatherMethod
재산있음
method

 

==> 그러나 부모가 정의한 method()가 좀 맘에 안들어서 그대로 갖다쓰지 않고 좀 바꿔서 쓰고 싶다면

Child.java에서 method() 정의

package com.day06;
//Father 상속
public class Child extends Father {
   public Child() {
	   //super(); -> 생략가능
      System.out.println("Child 생성자");
   }
   public void childMethod() {
      System.out.println("childMethod");
   }
   
   public void method() {
	      System.out.println("할아버지 method 수정"); //할아버지한테 method가 있는데 맘에 안들어서 조금 수정하고싶다.
	   }
}

 

GrandFather 생성자
grandFatherMethod
=============
GrandFather 생성자
Father 생성자
fatherMethod
grandFatherMethod
============
GrandFather 생성자
Father 생성자
Child 생성자
childMethod
fatherMethod
grandFatherMethod
재산있음
할아버지 method 수정 -> 할아버지의 method가 아닌 child가 정의한 method로 출력됨

-> 오버라이딩 : 상속관계에 있을 때 부모의 메소드를 자식이 재정의 하는 것

 

package com.day06;

public class Child extends Father {
	public Child() { //생성자
		//super(); 생략 가능
		System.out.println("Child 생성자");
	}
	public void childMethod() { //함수
		System.out.println("childMethod");
	}
	//오버라이딩
	//상속 관계에 있을 때 부모의 메소드를 자식이 재정의 하는 것
	public void method() {//부모의 method수정해서 사용
		System.out.println("할아버지의 method 수정"); //할아버지에게 있는 메서드지만 맘에 안들어서 자식이 재정의
	}
}

==> 부모에게 있는 메서드를 자동으로 오버라이딩 할 수 있도록 하려면

 

내가 직접 써주지 않아도 Ctrl + SpaceBar

 

 

쓸 수 있는 메서드가 다 나온다.

method()를 선택하고 Enter 치면

자동으로 오버라이딩 할 수 있도록 삽입됨

package com.day06;

public class Child extends Father {
	public Child() { //생성자
		//super(); 생략 가능
		System.out.println("Child 생성자");
	}
	public void childMethod() { //함수
		System.out.println("childMethod");
	}
	//오버라이딩
	//상속 관계에 있을 때 부모의 메소드를 자식이 재정의 하는 것
	@Override //애노테이션
	public void method() {
		// TODO Auto-generated method stub
		super.method();
	}
}

애노테이션이 있으면 'methods라는 함수는 부모한테 없는 함수인데 존재하지 않는 메서드를 가져다 재정의 한다고?!' 하면서 알려줌(부모에게 존재하는 함수 이름은 method임)

애노테이션이 없으면 부모의 함수를 재정의하는게 아니라 그냥 자기가 새로운 메소드(이름 : methods)를 정의하는 거니까 사용 가능함

 

package com.day06;

public class Child extends Father {
	public Child() { //생성자
		//super(); 생략 가능
		System.out.println("Child 생성자");
	}
	public void childMethod() { //함수
		System.out.println("childMethod");
	}
	//오버라이딩
	//상속 관계에 있을 때 부모의 메소드를 자식이 재정의 하는 것
	@Override //애노테이션
	public void method() { //부모에게 있는 method라는 함수를 가져다 재정의
		// TODO Auto-generated method stub
		super.method();
	}
}

이렇게 써주는 게 맞는 것

 

==> Main.java에서 Father객체 f1를 하나 더 생성

new ~ 로 생성하지 않았으므로 아직 생성이 되기 전 -> 생성자 호출XX

 

 

package com.day06;

public class Main {

	public static void main(String[] args) {
		GrandFather gf = new GrandFather();
		gf.grandfatherMethod();
		
		System.out.println("==Father가 GrandFather을 상속받은 후===");
		Father f = new Father();
		f.fatherMethod();
		System.out.println("==Father가 GrandFather의 함수 사용===");
		f.grandfatherMethod();
		System.out.println("==Child객체 생성==");
		Child c = new Child(); //자기 생성자한테 달려감
		System.out.println("==Child가 부모의 함수 사용===");
		c.childMethod(); //자기 자신의 함수는 당연히 사용 가능
		c.fatherMethod(); //Father를 상속 받았으므로 부모 Father의 함수 사용 가능
		c.grandfatherMethod(); //부모 Father이 GrandFather를 상속받았으므로 이 또한 사용 가능
		System.out.println(c.value);
		c.method();// 상속 받았으므로 할아버지의 메소드 사용 가능
		System.out.println("===============");
		//Father 객체 하나 더 만들기(이름 : f1)
		Father f1; //Father f1 = new Father();를 하지 않았으므로 아직 생성 전!
		Child c1 = new Child(); //f1은 아직 생성x -> 생성자 호출X, c1은 생성O -> 생성자 호출O
		
		//f1은 Father형이지만 Child의 오버라이딩 된 메소드 사용 가능
		f1 = c1; //f1은 Father형, c1은 Child형으로 다르지만 에러가 나지 않음
		// -> whi? 상위 개념인 Father에 하위 개념인 Child를 넣을 수 있음
		// -> 이렇게 해준다고 해서 f1이 Child형이 되거나 c1이 Father형이 되는 등 형이 변하는 건 아님
		//f1.childMethod(); //따라서 부모는 여전히 자식의 메소드를 사용할 수 없음
		f1.method(); // 그러나 오버라이딩되어 Child가 재정의한 것은 사용 가능
	}
}

 

다르게 표헌하기

package com.day06;

public class Main {

   public static void main(String[] args) {
      GrandFather gf=new GrandFather();
      gf.grandFatherMethod();
      System.out.println("=============");
      Father f=new Father();
      f.fatherMethod();
      
      f.grandFatherMethod(); //Father에 extends를 사용하지 않으면 오류가 나지만 extends 사용으로 오류x 상속받음?
      System.out.println("============");
      Child c=new Child();
      c.childMethod(); //자기것 사용 가능
      c.fatherMethod(); //상속 받은 아버지것 사용 가능
      c.grandFatherMethod(); //상속 받은 아버지의 아버지 -> 할아버지것 사용 가능
      System.out.println(c.value);
      c.method();
      System.out.println("============");
      //Father 하나 더 만들기
      Father f1; //아직 new를 하지 않아서 객체가 만들어지지 않았음
      Child c1 = new Child(); //f1은 생성X, c1은 생성O
      
      //f1은 Father 형이지만 Child의 오버라이딩 된 메소드 사용 가능
      f1 = c1; //f1과 c1은 서로 Father형, Child형으로 다른데 에러가 안난다 -> why? Child의 상위의 개념인 Father에 넣을 수 있다.
      		   //서로 형이 변하는 것은 아니다.
      //f1.childMethod(); //따라서 이것은 사용할 수 없음
      f1.method(); //그러나 오버라이딩 된 것은 사용 가능
      
      Father f2 = new Child(); //서로 형이 다르나 상속 관계이고, 좌측의 Father이 더 상위 개념이기 때문에 이렇게 써줄 수 있다.
   }
}

Father.java에서도 Ctrl + SpaceBar 해서 method 선택 후 바꿔보기

package com.day06;

public class Father extends GrandFather { //***extends 부모의 ~를 먼저 실행
   public Father() {
      //super(); ***super 생략가능
      System.out.println("Father 생성자");
   }

   public void fatherMethod() {
      System.out.println("fatherMethod");
   }
   
   @Override
	public void method() {
		System.out.println("아버지가 할아버지의 method 재정의");
	}
}

GrandFather 생성자
grandFatherMethod
=============
GrandFather 생성자
Father 생성자
fatherMethod
grandFatherMethod
============
GrandFather 생성자
Father 생성자
Child 생성자
childMethod
fatherMethod
grandFatherMethod
재산있음
Child가 할아버지의 method 재정의
============
GrandFather 생성자
Father 생성자
Child 생성자
Child가 할아버지의 method 재정의
GrandFather 생성자
Father 생성자
Child 생성자
Child가 할아버지의 method 재정의

 

==> Father객체 f2가 자기 자신의 함수 fatherMethod 호출

package com.day06;

public class Main {

   public static void main(String[] args) {
      GrandFather gf=new GrandFather();
      gf.grandFatherMethod();
      System.out.println("=============");
      Father f=new Father();
      f.fatherMethod();
      
      f.grandFatherMethod(); //Father에 extends를 사용하지 않으면 오류가 나지만 extends 사용으로 오류x 상속받음?
      System.out.println("============");
      Child c=new Child();
      c.childMethod(); //자기것 사용 가능
      c.fatherMethod(); //상속 받은 아버지것 사용 가능
      c.grandFatherMethod(); //상속 받은 아버지의 아버지 -> 할아버지것 사용 가능
      System.out.println(c.value);
      c.method();
      System.out.println("============");
      //Father 하나 더 만들기
      Father f1; //아직 new를 하지 않아서 객체가 만들어지지 않았음
      Child c1 = new Child(); //f1은 생성X, c1은 생성O
      
      //f1은 Father 형이지만 Child의 오버라이딩 된 메소드 사용 가능
      f1 = c1; //f1과 c1은 서로 Father형, Child형으로 다른데 에러가 안난다 -> why? Child의 상위의 개념인 Father에 넣을 수 있다.
      		   //서로 형이 변하는 것은 아니다.
      //f1.childMethod(); //따라서 이것은 사용할 수 없음
      f1.method(); //그러나 오버라이딩 된 것은 사용 가능
      
      //f2는 Father형이고 오버라이딩 된 메소드는 Child 것을 사용
      Father f2 = new Child(); //서로 형이 다르나 상속 관계이고, 좌측의 Father이 더 상위 개념이기 때문에 이렇게 써줄 수 있다.
      f2.method();
      //f2.childMethod(); // 오류발생
      f2.fatherMethod();
      
   }
}

GrandFather 생성자
grandFatherMethod
=============
GrandFather 생성자
Father 생성자
fatherMethod
grandFatherMethod
============
GrandFather 생성자
Father 생성자
Child 생성자
childMethod
fatherMethod
grandFatherMethod
재산있음
Child가 할아버지의 method 재정의
============
GrandFather 생성자
Father 생성자
Child 생성자
Child가 할아버지의 method 재정의
GrandFather 생성자
Father 생성자
Child 생성자
Child가 할아버지의 method 재정의
fatherMethod -> Father 자신의 Method 나옴


TV, ColorTV, IPTV, TVMain 클래스 만들기

부모 TV.java는 공통적인 것을가짐 -> ColorTV, IPTV, TV 할것 없이 모든 TV는 Size라는 공통점을 가짐

TV.java

package com.day06;
//모든 TV의 부모 클래스
public class TV {
	private int size;
	public TV(int size) {//생성자
	this.size = size;
	}
	
	public int getSize() { //size물어보면 알려줘야 하니까 getter만들기
		return size;
	}
}

TVMain.java

package com.day06;

public class TVMain {

	public static void main(String[] args) {
		ColorTV mytv = new ColorTV(32, 1024); //32인치, 1024 컬러
		mytv.print(); //32인치 1024컬러
		
		IPTV iptv = new IPTV("192.1.1.2", 32, 2048);
		iptv.print(); //나의 TV는 192.1.1.2 주소의 32인치 2048 컬러
	}
}

==> 오류 없애주기 -> 생성자가 빠져서 오류가 난다.

TV.java

package com.day06;

public class TV {
	private int size;
	public TV(int size) { //생성자
		this.size = size;
	}
	
	protected int getSize() { //크기 알려줌
		return size;
	}
}

ColorTV.java

package com.day06;

public class ColorTV {
	private int size, color;
	public ColorTV(int size, int color) { //생성자
		this.size = size;
		this.color = color;
	}

	public void print() { //함수
		//32인치 1024컬러
		System.out.println("나의 TV는 " + size + "인치 " + color + "컬러");
	}
	
}

IPTV.java

package com.day06;

public class IPTV {
	private String ip;
	private int size, color;
	public IPTV(String ip, int size, int color) {
		this.ip = ip;
		this.size = size;
		this.color = color;
	}
	
	public void print() {
		System.out.println("나의 TV는 " + ip + " 주소의 " + size + "인치 " + color + "컬러");
	}
}

TVMain.java

package com.day06;

public class TVMain {
	
	public static void main(String[] args) {
		ColorTV mytv = new ColorTV(32, 1024); //32인치, 1024 컬러
		mytv.print(); //32인치 1024컬러
		
		IPTV iptv = new IPTV("192.1.1.2", 32, 2048);
		iptv.print(); //나의 TV는 192.1.1.2 주소의 32인치 2048 컬러
	}
}

나의 TV는 32인치 1024컬러
나의 TV는 192.1.1.2 주소의 32인치 2048컬러

 

상속을 하지 않아도 답은 나온다.

 

 

상속 관계로 바꾸어 볼 것>>

 

2개 공통점??

ColorTV에서 TV를 상속받자

상속을 받으면 부모의 default 생성자로 간다.

size는 부모에게도 있으니 그걸 갖다 쓰고

super(size);

package com.day06;

public class ColorTV extends TV {
	private int color;
	public ColorTV(int size, int color) { //생성자
		super(size); //IPTV와 공통적으로 가지고 있으니 부모걸 그대로 쓰면 됨
		this.color = color;
	}
	//@Override 불가능 -> 부모 TV에는 없는 메소드이고 자식인 IPTV의 입장에서는 여기의 print()가 원본 메소드임
	public void print() { //함수
		//32인치 1024컬러
		System.out.println(getSize() + "인치 " + color + "컬러");
	}
	
}

==> IPTV도 혼자 갖는 속성 ip를 제외하면 size, color가 부모 ColorTV와 공통됨

package com.day06;

public class IPTV extends ColorTV {
	private String ip;
	//private int size, color; -> 부모 colorTV에 color 있고, TV에 size있으므로 없애줌
	public IPTV(String ip, int size, int color) {
		super(size, color);
		this.ip = ip;
		//this.size = size;
		//this.color = color;
	}
	@Override
	public void print() {
		//System.out.println("나의 TV는 " + ip + " 주소의 " + size + "인치 " + color + "컬러");
		System.out.print("나의 TV는 " + ip + " 주소의 ");
		super.print();//부모에서 인치, 컬러 출력하고 있으니 그걸 가져다 씀
	}
}

print() 메소드는 부모에게도 있는 메소드이고 ip 주소를 출력하는 것만 다르고 나머지 인치, 컬러 출력은 동일 하므로

부모것을 갖다가 사용

 

나의 TV는 32인치 1024컬러
나의 TV는 192.1.1.2 주소의 나의 TV는 32인치 2048컬러

 

결과는 계속 동일

 

==> TVMain.java

package com.day06;

public class TVMain {
	
	public static void main(String[] args) {
		ColorTV mytv = new ColorTV(32, 1024); //32인치, 1024 컬러
		mytv.print(); //32인치 1024컬러
		
		//IPTV iptv = new IPTV("192.1.1.2", 32, 2048); //이렇게 써줘도 되고
		ColorTV iptv = new IPTV("192.1.1.2", 32, 2048);//부모(상위) 형으로 적어줘도 된다
		iptv.print(); //나의 TV는 192.1.1.2 주소의 32인치 2048 컬러
	}
}

32인치 1024컬러
나의 TV는 192.1.1.2 주소의 32인치 2048컬러

 

결과 계속 동일


ProductMain.java 클래스! 각각의 Product, PTV, Computer, Audio 클래스를 위처럼 따로 따로 안 만들고 모두 ProductMain.java 클래스 안에 같이 만들어서 상속도 시키고 해볼 것

 

일단 객체 생성

- 물건들 : PTV, Computer, Audio의 객체 생성

- 물건을 구매할 구매자 : Buyer의 객체 생성

- 행위 : Buyer가 물건 구매 , 바이어가 구매한 구매 내역 보기

 

==> 객체 생성을 위해 클래스 만들기 -> 따로 따로 클래스 생성 X, ProductMain.java에 다같이 만들어 줄 것

- 객체를 만드려면 클래스가 필요함

- Buyer, PTV, Computer, Audio 클래스 -> 이들이 상품들이 공통적으로 가지는 특성을 가진 상위 클래스, 부모 클래스인 Product 클래스 생성

==> 각각의 클래스가 가지는 속성과 함수 채워넣기

Product는 아래 PTV, Computer, Audio 상품들(클래스들)의 부모가 될 건데 공동된 속성 price, bonusPoint를 private으로 선언해버리면 자식들에게 상속한다 해도 자식들이 접근해서 사용할 수 없으므로 protected로 선언해주어야 한다.

==> 아직까지 상속받기 전

==> 구매자 Buyer의 객체 b는 구매하고 구매한 물품을 보는 행위를 할 수 있으므로

Buyer 클래스 안에 함수 buy()와 show()를 만들어 줌

그러나 함수 buy()를 만들어주기는 했으나 main부에서 Buyer의 객체 b가 buy()를 할 때 Computer를 구매할 수도 있고, PTV나 Audio를 구매할 수도 있다 -> buy() 안에 PTV의 객체 ptv나 Computer의 객체 com이나 Audio의 객체 audio가 올 수 있다는 말!

-> Buyer 클래스에서 만들어준 함수 buy0는 아직까지 무슨 형의 뭘 받아올지 몰라서 비워둔 상태이므로,

main부에서 buy(ptv), buy(com)처럼 인자가 있는게 아니라서 Error가 발생

-> 그렇다면 Buyer 클래스의 함수 buy0는 무슨 형을 받아와야 할까? ptv, com, audio를 살 경우를 대비해 모두 각각 적어주기에는 번거로움 -> 무엇을 구매할지 알 수 없으니 이 모든 제품을 아우르는 형이 필요함 -> 그것이 바로 Product임! -> 따라서 buy()는 Product형을 받아옴(Product형의 받아오는 것의 이름은 내맘대로 p로 지어주겠음) & Computer, Audio, Buyer 클래스가 각각 Product를 상속 받도록 해주기!

==> Buyer가 물건 구매 시

1. 물건 가격 만큼을 소지한 돈에서 차감

2. 포인트 적립 받음 : 현재 소지한 포인트 + 해당 물건 구매 가격의 10%(이미 Product에서 계산하여 bonusPoint라는 이름으로 저장해놓음)

==> Buyer가 쇼핑을 할 때 1개만 살 수도 있지만 여러 물품을 구매할 수도 있기 때문에 구매한 물품을 저장해 두어야 함 -> 저장소 필요 : 배열이나 ArrayList에 저장될 것이 예상됨

1. 먼저 구매한 물품을 저장할 배열(이름 : arr) 만들기 -> 이 때 배열의 유형은 Product!

Product형의 배열 arr을 만들었는데 Buyer가 몇개를 구매할 지 모르니까 배열의 길이는 충분하게! 크게 만들어 줘야 함

==> 구매하면 배열에 저장되도록 하기

이 때 arr[0]부터 저장하고 구매할 때마다 1 2 3 4 .. 에 각각 저장해주어야 하므로 저장해주고 +1이 될 수 있도록 안에 인수 임의로 만들어주기!(이름 : cnt)

물품을 구매 but(Product p) 하면 후위 연산자이므로 해당 물품을 arr[0]에 저장한 뒤 cnt가 +1되어 다음 번 물건 구매 시 arr[1]에 저장하고 +1되어 arr[2].. 됨

 

==> 구매 물건 보기 show() 시 배열에 저장된 구매 내역이 출력되도록 하기

==> 총 구매 금액을 알 수 있도록 변수 sum을 만들어서 구매한 상품들의 금액을 더해주기

==> 여기까지 실행

구매 내역을 출력하면 구매 상품의 이름이 아니라 arr[0], arr[1]의 주소값이 나옴

내가 원하는 출력물은

구매상품 : TV 
구매상품 : Computer 
총 구매 금액 : 220

남은 돈 : 780

포인트 : 22

 

==> toString()을 오버라이딩해서 return값을 내가 원하는 "TV", "Computer"로 재정의 해주기

toString()에게 달려가서 출력해주니까 toString()을 오버라이딩해서 주소값이 아닌 내가 원하는 상품의 이름으로 출력되도록 재정의 해줌

==> 전체 코드

package com.day06;

class Product { // 가격, 보너스 포인트(자식들의 공통된 속성)를 가짐
	//private int price, bonusPoint; //가격, 포인트 -> 상속 받는 자식이 사용할 수 있게 protected로 써주기
	protected int price, bonusPoint; //보너스 포인트는 제품 가격의 10%를 적립 받음
	
	public Product(int price) { //생성자 -> 가격을 받아 저장, 클래스 이름(Product)으로 적어줘야 함
		this.price = price; //가격을 알면 보너스 포인트 계산 가능
		this.bonusPoint += price * 0.1; // 제품 가격의 10% 즉 0.1 적립
	}
} //Product 닫기 - 생성자 까지가 한 덩어리!

class PTV extends Product {
	public PTV(int price) { //생성자
		super(price); //price를 부모한테 줌
	}
	
	@Override
	public String toString() {
		return "PTV";
	}
}

class Computer extends Product {
	public Computer(int price) { //생성자
		super(price);
	}
	
	@Override
	public String toString() {
		return "Computer";
	}
}

class Audio extends Product {
	public Audio(int price) { //생성자
		super(price);
	}
	
	@Override
	public String toString() {
		return "Audio";
	}
}

//위의 나열된 물건들을 사러 올 손님 필요(Product - PTV, Computer, Audio 구매 가능)
class Buyer { //속성 : 돈(돈이 있어야 구매 가능), 함수 : 물건 구매(포인트 적립됨), 구매한 물건 보기
	private int money, point; //돈, 적립된 포인트 가짐
	private Product[] arr = new Product[100]; //구매한 물품을 저장할 배열 만들기 -> 몇 개 구매할지 모르니까 넉넉하게 크기 100으로 잡음
	private int cnt; //구매 물품 개수이자 arr[0]부터 1 2 3 ..에 구매한 물품을 차곡차곡 저장하기 위해 만든 변수 cnt
	
	public Buyer(int money) { //구매할 수 있도록 생성자 만듦 -> 일정 금애의 돈을 가진 객체를 Main에서 생성해주면
		this.money = money; //해당 금액을 가짐
	}
	
	//물건사다 : 구매하는 함수 -> 돈은 차감, 포인트는 적립, 구매 내역에 구매한 물품 추가(저장소 필요 - 배열/ArrayList 등에 저장할 수 있을 것)
	public void buy(Product p) { //뭘 구매할지 모르니 구매하는 물품의 형은 부모 유형 Product가 됨!
		money -= p.price; //구매한 물건 p의 가격만큼 소지한 돈 차감
		point += p.bonusPoint; //구매 물건 p 가격의 10% 만큼의 bonusPoint(미리 계산해둠)를 적립받음
		//구매한 Product p 배열에 차곡차곡 저장
		arr[cnt++] = p; // 후위 연산자 일단 0에 저장 후 cnt는 +1됨
	}
	
	public void show() {//구매 내역을 보는 함수 -> 현재 가진 돈, 포인트, 구매한 내역을 알려줌
		int sum = 0;
		for(int i = 0; i < cnt; i++) { //arr.length하면 0~99까지 100개 끝까지 다 도니까 구매한 갯수 cnt만큼만 돌림!
			System.out.println("구매상품 : " + arr[i]); //구매 상품은 여러개 일 수 있으므로 for문 돌려서 출력
			sum += arr[i].price;
		}
		System.out.println("총 구매 금액 : " + sum);
		System.out.println("남은 돈 : " + money); //구매하고 남은 돈 알려줌
		System.out.println("포인트 : " + point); //Buyer의 포인트
	}
}

public class ProductMain { 
	
	public static void main(String[] args) { //객체를 생성해서 물건을 구매하는 부분
		Buyer b = new Buyer(1000); //구매자 만듦 1000만원 소지
		PTV ptv = new PTV(100); //구매할 물건 만듦, ptv 가격 100만원
		Computer com = new Computer(120);
		Audio audio = new Audio(70);
		
		b.buy(ptv);//구매자 b가 ptv를 구매 -> 에러 : 내가 만든 buy에는 인자가 없다 -> ptv는 무슨 형? PTV형
		b.buy(com);//구매자 b가 computer 구매 -> 에러 : 내가 만든 buy에는 인자가 없다 -> com는 무슨 형? Computer형
		
		b.show();//구매자 b의 구매 내역 보기
	}//main 종료

}//ProductMain 종료

구매상품 : PTV
구매상품 : Computer
총 구매 금액 : 220
남은 돈 : 780
포인트 : 22

 

==> audio도 구매해보자

b.buy(audio);//audio도 구매함

오디오 구매 전                                           후 결과

구매상품 : TV
구매상품 : Computer
구매상품 : 오디오 -> 추가됨!

총 구매 금액 : 290

남은 돈 : 710
포인트 : 29

 

전체 코드

package com.day06;

class Product { // 가격, 보너스 포인트(자식들의 공통된 속성)를 가짐
	//private int price, bonusPoint; //가격, 포인트 -> 상속 받는 자식이 사용할 수 있게 protected로 써주기
	protected int price, bonusPoint; //보너스 포인트는 제품 가격의 10%를 적립 받음
	
	public Product(int price) { //생성자 -> 가격을 받아 저장, 클래스 이름(Product)으로 적어줘야 함
		this.price = price; //가격을 알면 보너스 포인트 계산 가능
		this.bonusPoint += price * 0.1; // 제품 가격의 10% 즉 0.1 적립
	}
} //Product 닫기 - 생성자 까지가 한 덩어리!

class PTV extends Product {
	public PTV(int price) { //생성자
		super(price); //price를 부모한테 줌
	}
	
	@Override
	public String toString() {
		return "PTV";
	}
}

class Computer extends Product {
	public Computer(int price) { //생성자
		super(price);
	}
	
	@Override
	public String toString() {
		return "Computer";
	}
}

class Audio extends Product {
	public Audio(int price) { //생성자
		super(price);
	}
	
	@Override
	public String toString() {
		return "Audio";
	}
}

//위의 나열된 물건들을 사러 올 손님 필요(Product - PTV, Computer, Audio 구매 가능)
class Buyer { //속성 : 돈(돈이 있어야 구매 가능), 함수 : 물건 구매(포인트 적립됨), 구매한 물건 보기
	private int money, point; //돈, 적립된 포인트 가짐
	private Product[] arr = new Product[100]; //구매한 물품을 저장할 배열 만들기 -> 몇 개 구매할지 모르니까 넉넉하게 크기 100으로 잡음
	private int cnt; //구매 물품 개수이자 arr[0]부터 1 2 3 ..에 구매한 물품을 차곡차곡 저장하기 위해 만든 변수 cnt
	
	public Buyer(int money) { //구매할 수 있도록 생성자 만듦 -> 일정 금애의 돈을 가진 객체를 Main에서 생성해주면
		this.money = money; //해당 금액을 가짐
	}
	
	//물건사다 : 구매하는 함수 -> 돈은 차감, 포인트는 적립, 구매 내역에 구매한 물품 추가(저장소 필요 - 배열/ArrayList 등에 저장할 수 있을 것)
	public void buy(Product p) { //뭘 구매할지 모르니 구매하는 물품의 형은 부모 유형 Product가 됨!
		money -= p.price; //구매한 물건 p의 가격만큼 소지한 돈 차감
		point += p.bonusPoint; //구매 물건 p 가격의 10% 만큼의 bonusPoint(미리 계산해둠)를 적립받음
		//구매한 Product p 배열에 차곡차곡 저장
		arr[cnt++] = p; // 후위 연산자 일단 0에 저장 후 cnt는 +1됨
	}
	
	public void show() {//구매 내역을 보는 함수 -> 현재 가진 돈, 포인트, 구매한 내역을 알려줌
		int sum = 0;
		for(int i = 0; i < cnt; i++) { //arr.length하면 0~99까지 100개 끝까지 다 도니까 구매한 갯수 cnt만큼만 돌림!
			System.out.println("구매상품 : " + arr[i]); //구매 상품은 여러개 일 수 있으므로 for문 돌려서 출력
			sum += arr[i].price;
		}
		System.out.println("총 구매 금액 : " + sum);
		System.out.println("남은 돈 : " + money); //구매하고 남은 돈 알려줌
		System.out.println("포인트 : " + point); //Buyer의 포인트
	}
}

public class ProductMain { 
	
	public static void main(String[] args) { //객체를 생성해서 물건을 구매하는 부분
		Buyer b = new Buyer(1000); //구매자 만듦 1000만원 소지
		PTV ptv = new PTV(100); //구매할 물건 만듦, ptv 가격 100만원
		Computer com = new Computer(120);
		Audio audio = new Audio(70);
		
		b.buy(ptv);//구매자 b가 ptv를 구매 -> 에러 : 내가 만든 buy에는 인자가 없다 -> ptv는 무슨 형? PTV형
		b.buy(com);//구매자 b가 computer 구매 -> 에러 : 내가 만든 buy에는 인자가 없다 -> com는 무슨 형? Computer형
		b.buy(audio); //오디오도 구매함
		
		b.show();//구매자 b의 구매 내역 보기
	}//main 종료

}//ProductMain 종료

 

자바에서의 최상위 객체 : Object

Object는 어디에 들어있을까? 기본 : java.lang 이라는 package에 들어있을 것

이때까지 따로 import를 안해줬다 -> 기본에 있는 건 다 java.lang에 있었을 것

자바에서 최상위는 Object이기 때문에 다 상속받을 수 있다.

반환해준다

객체 : 주소값을 가진다 -> 이걸 내가 알아들을 수 없으니 오버라이딩 시킴

System.out.println(); -> toString() 부르게 되어있다.

Object가 가지고 있는 건 다 오버라이딩 할 수 있다.

- 최상위 객체이므로 무조건 상속됨

 

ProductMain2.java -> ProductMain.java 그대로 복사

- 이미 있는 것들이라 에러가 나니까 다 2 로 고쳐주기

 

==> 배열을 ArrayList alist로 수정하기

배열 arr을 ArrayList로 변경해주기 -> ArrayList는 import 시켜야 함

 

alist의 자료형은 Product2

결과는 배열을 사용했을 때와 동일함

==> 전체 코드

package com.day06;

import java.util.ArrayList;

//ProductMain에서는 배열 arr을 이용했던 것을 2에서는 ArrayList alist로 수정하기
class Product2 { // 가격, 보너스 포인트(자식들의 공통된 속성)를 가짐
	//private int price, bonusPoint; //가격, 포인트 -> 상속 받는 자식이 사용할 수 있게 protected로 써주기
	protected int price, bonusPoint; //보너스 포인트는 제품 가격의 10%를 적립 받음
	
	public Product2(int price) { //생성자 -> 가격을 받아 저장, 클래스 이름(Product)으로 적어줘야 함
		this.price = price; //가격을 알면 보너스 포인트 계산 가능
		this.bonusPoint += price * 0.1; // 제품 가격의 10% 즉 0.1 적립
	}
} //Product 닫기 - 생성자 까지가 한 덩어리!

class PTV2 extends Product2 {
	public PTV2(int price) { //생성자
		super(price); //price를 부모한테 줌
	}
	
	@Override
	public String toString() {
		return "PTV";
	}
}

class Computer2 extends Product2 {
	public Computer2(int price) { //생성자
		super(price);
	}
	
	@Override
	public String toString() {
		return "Computer";
	}
}

class Audio2 extends Product2 {
	public Audio2(int price) { //생성자
		super(price);
	}
	
	@Override
	public String toString() {
		return "Audio";
	}
}

//위의 나열된 물건들을 사러 올 손님 필요(Product - PTV, Computer, Audio 구매 가능)
class Buyer2 { //속성 : 돈(돈이 있어야 구매 가능), 함수 : 물건 구매(포인트 적립됨), 구매한 물건 보기
	private int money, point; //돈, 적립된 포인트 가짐
	//private Product2[] arr = new Product2[100]; //구매한 물품을 저장할 배열 만들기 -> 몇 개 구매할지 모르니까 넉넉하게 크기 100으로 잡음
	//private int cnt; //구매 물품 개수이자 arr[0]부터 1 2 3 ..에 구매한 물품을 차곡차곡 저장하기 위해 만든 변수 cnt
	private ArrayList<Product2> alist = new ArrayList<>(); //private는 써도 되고 안써줘도 된다.
	
	public Buyer2(int money) { //구매할 수 있도록 생성자 만듦 -> 일정 금애의 돈을 가진 객체를 Main에서 생성해주면
		this.money = money; //해당 금액을 가짐
	}
	
	//물건사다 : 구매하는 함수 -> 돈은 차감, 포인트는 적립, 구매 내역에 구매한 물품 추가(저장소 필요 - 배열/ArrayList 등에 저장할 수 있을 것)
	public void buy(Product2 p) { //뭘 구매할지 모르니 구매하는 물품의 형은 부모 유형 Product가 됨!
		money -= p.price; //구매한 물건 p의 가격만큼 소지한 돈 차감
		point += p.bonusPoint; //구매 물건 p 가격의 10% 만큼의 bonusPoint(미리 계산해둠)를 적립받음
		//구매한 Product p 배열에 차곡차곡 저장
		//arr[cnt++] = p; // 후위 연산자 일단 0에 저장 후 cnt는 +1됨
		alist.add(p);
	}
	
	public void show() {//구매 내역을 보는 함수 -> 현재 가진 돈, 포인트, 구매한 내역을 알려줌
		int sum = 0;
		for(int i = 0; i < alist.size(); i++) { //alist의 사이즈 만큼만 돌림!
			System.out.println("구매상품 : " + alist.get(i)); //구매 상품은 여러개 일 수 있으므로 for문 돌려서 출력
			sum += alist.get(i).price;
		}
		System.out.println("총 구매 금액 : " + sum);
		System.out.println("남은 돈 : " + money); //구매하고 남은 돈 알려줌
		System.out.println("포인트 : " + point); //Buyer의 포인트
	}
}

public class ProductMain2 { 
	
	public static void main(String[] args) { //객체를 생성해서 물건을 구매하는 부분
		Buyer2 b = new Buyer2(1000); //구매자 만듦 1000만원 소지
		PTV2 ptv = new PTV2(100); //구매할 물건 만듦, ptv 가격 100만원
		Computer2 com = new Computer2(120);
		Audio2 audio = new Audio2(70);
		
		b.buy(ptv);//구매자 b가 ptv를 구매 -> 에러 : 내가 만든 buy에는 인자가 없다 -> ptv는 무슨 형? PTV형
		b.buy(com);//구매자 b가 computer 구매 -> 에러 : 내가 만든 buy에는 인자가 없다 -> com는 무슨 형? Computer형
		b.buy(audio); //오디오도 구매함
		
		b.show();//구매자 b의 구매 내역 보기
	}//main 종료

}//ProductMain 종료

==> 만약 구매자 b가 반품을 한다면? b.refund(반품할 객체); 추가

 

구매한 컴퓨터 반품 : b.refund(com);

==> 작성해보기

==> 전체 코드

package com.day06;

import java.util.ArrayList;

//ProductMain에서는 배열 arr을 이용했던 것을 2에서는 ArrayList alist로 수정하기
class Product2 { // 가격, 보너스 포인트(자식들의 공통된 속성)를 가짐
	//private int price, bonusPoint; //가격, 포인트 -> 상속 받는 자식이 사용할 수 있게 protected로 써주기
	protected int price, bonusPoint; //보너스 포인트는 제품 가격의 10%를 적립 받음
	
	public Product2(int price) { //생성자 -> 가격을 받아 저장, 클래스 이름(Product)으로 적어줘야 함
		this.price = price; //가격을 알면 보너스 포인트 계산 가능
		this.bonusPoint += price * 0.1; // 제품 가격의 10% 즉 0.1 적립
	}
} //Product 닫기 - 생성자 까지가 한 덩어리!

class PTV2 extends Product2 {
	public PTV2(int price) { //생성자
		super(price); //price를 부모한테 줌
	}
	
	@Override
	public String toString() {
		return "PTV";
	}
}

class Computer2 extends Product2 {
	public Computer2(int price) { //생성자
		super(price);
	}
	
	@Override
	public String toString() {
		return "Computer";
	}
}

class Audio2 extends Product2 {
	public Audio2(int price) { //생성자
		super(price);
	}
	
	@Override
	public String toString() {
		return "Audio";
	}
}

//위의 나열된 물건들을 사러 올 손님 필요(Product - PTV, Computer, Audio 구매 가능)
class Buyer2 { //속성 : 돈(돈이 있어야 구매 가능), 함수 : 물건 구매(포인트 적립됨), 구매한 물건 보기
	private int money, point; //돈, 적립된 포인트 가짐
	//private Product2[] arr = new Product2[100]; //구매한 물품을 저장할 배열 만들기 -> 몇 개 구매할지 모르니까 넉넉하게 크기 100으로 잡음
	//private int cnt; //구매 물품 개수이자 arr[0]부터 1 2 3 ..에 구매한 물품을 차곡차곡 저장하기 위해 만든 변수 cnt
	private ArrayList<Product2> alist = new ArrayList<>(); //private는 써도 되고 안써줘도 된다.
	
	public Buyer2(int money) { //구매할 수 있도록 생성자 만듦 -> 일정 금애의 돈을 가진 객체를 Main에서 생성해주면
		this.money = money; //해당 금액을 가짐
	}
	
	//물건사다 : 구매하는 함수 -> 돈은 차감, 포인트는 적립, 구매 내역에 구매한 물품 추가(저장소 필요 - 배열/ArrayList 등에 저장할 수 있을 것)
	public void buy(Product2 p) { //뭘 구매할지 모르니 구매하는 물품의 형은 부모 유형 Product가 됨!
		money -= p.price; //구매한 물건 p의 가격만큼 소지한 돈 차감
		point += p.bonusPoint; //구매 물건 p 가격의 10% 만큼의 bonusPoint(미리 계산해둠)를 적립받음
		//구매한 Product p 배열에 차곡차곡 저장
		//arr[cnt++] = p; // 후위 연산자 일단 0에 저장 후 cnt는 +1됨
		alist.add(p);
	}
	
	public void refund(Product2 p) {
		money += p.price; //반품할 문검 가격만큼 소지한 돈 다시 돌려 받음
		point -= p.bonusPoint; //적립된 포인트 다시 회수
		alist.remove(p); //구매 리스트 alist에서 해당 제품 제거
	}
	
	public void show() {//구매 내역을 보는 함수 -> 현재 가진 돈, 포인트, 구매한 내역을 알려줌
		int sum = 0;
		for(int i = 0; i < alist.size(); i++) { //alist의 사이즈 만큼만 돌림!
			System.out.println("구매상품 : " + alist.get(i)); //구매 상품은 여러개 일 수 있으므로 for문 돌려서 출력
			sum += alist.get(i).price;
		}
		System.out.println("총 구매 금액 : " + sum);
		System.out.println("남은 돈 : " + money); //구매하고 남은 돈 알려줌
		System.out.println("포인트 : " + point); //Buyer의 포인트
	}
}

public class ProductMain2 { 
	
	public static void main(String[] args) { //객체를 생성해서 물건을 구매하는 부분
		Buyer2 b = new Buyer2(1000); //구매자 만듦 1000만원 소지
		PTV2 ptv = new PTV2(100); //구매할 물건 만듦, ptv 가격 100만원
		Computer2 com = new Computer2(120);
		Audio2 audio = new Audio2(70);
		
		b.buy(ptv);//구매자 b가 ptv를 구매 -> 에러 : 내가 만든 buy에는 인자가 없다 -> ptv는 무슨 형? PTV형
		b.buy(com);//구매자 b가 computer 구매 -> 에러 : 내가 만든 buy에는 인자가 없다 -> com는 무슨 형? Computer형
		b.buy(audio); //오디오도 구매함
		//구매자가 반품 원함
		b.refund(com); //반품 -> 구매리스트 alist에서 제거, 구매자 돈 +, 적립된 포인트 -
		
		b.show();//구매자 b의 구매 내역 보기
	}//main 종료

}//ProductMain 종료

 

Computer 반품 전                                반품 후 결과


객체지향의 특징

1. 캡슐화

2. 상속

3. 다형성(오버로딩, 오버라이딩)

 

[클래스의 상속]

B 클래스가 A 클래스에서 상속받는다

- A클래스 : 상위 클래스(부모 클래스, parent class)

- B클래스 : 하위 클래스(자식 클래스, child class)

- A 클래스가 B 클래스에게 상속한다 = B클래스가 A클래스를 상속받는다

화살표 방향 : 클래스 간 상속을 표현할 때는 상속 받는 클래스에서 -> 상속하는 클래스로 화살표가 감

 

[클래스 상속 문법]

- 예약어 extends 사용 : 연장, 확장하다 -> A가 가지고 있는 속성이나 기능을 추가로 확장하여 B 클래스를 구현한다.

class B extends A { //B클래스 -> A클래스를 상속 받는다.

}

- 일반적인 슬래스 A에서 더 구체적인 클래스 B가 구현됨

 

2. 상속에서 클래스 생성과 형 변환

- 사람과 포유류의 관계는 어떻게 나타낼 수 있을까?

- 포유류 <- 사람 : 사람보다 포유류가 더 일반적인 개념

-> 사람은 포유류의 특징과 기능을 기본으로 더 많거나 다른 특징과 기능을 가지고 있다(더 구체적이다).

 

- 상위 클래스 : 보다 일반적인 개념

- 하위 클래스 : 보다 구체적인 클래스

 

[상속을 사용하여 고객 관리 프로그램 구현하기]

Customer.java 고객 클래스

- 속성(멤버변수) : 고객 아이디, 고객 이름, 고객 등급, 보너스 포인트, 보너스 포인트 적립 비율

package com.day06;
//상속을 사용하여 고객 관리 프로그램 구현하기
public class Customer { //속성(멤버변수) : 고객 아이디, 고객 이름, 고객 등급, 보너스 포인트, 보너스 포인트 적립 비율
	private String custID, custName, custGrade; //고객 아이디, 고객 이름, 고객 등급
	private int bonusPoint; //보너스 포인트
	double bonusRatio; //보너스 포인트 적립 비율
	
	public Customer() { //디폴트 생성자
		custGrade = "SILVER"; //모든 고객의 기본 등급은 SILVER
		bonusRatio = 0.01; //모든 고객의 기본 보너스 포인트 적립 비율 : 1% 즉 0.01
	}
	//함수
	public int calPrice(int price) { //상품 금액을 받아 계산하는 메서드(보너스 포인트 적립, 지불, 가격 계산)
		bonusPoint += price * bonusRatio; // 상품 금엑 price에 따라 보너스 포인트 적립만 하고
		return price; // 상품 금액 반환 -> 일반 고객은 상품 할인 없이 적립만 받고 원가 그대로 사야 함
	}
	
	public String showCustInfo() { //고객 정보 출력하는 메서드
		return custName + "님의 등급은 " + custGrade + "이며, 보너스 포인트는 " + bonusPoint + "입니다.";
	}
}

[멤버 변수] :  고객 아이디, 이름, 등급, 보너스 포인트, 포인트 적립 비율

- 모든 멤버 변수를 반드시 private로 선언할 필요는 없다. 필요에 따라 멤버 변수나 메서드를 외부에 노출하지 않을 목적일 때 private로 선언

[메서드]

- Customer() : 기본 생성자

- calPrice(int price) : 제품에 대해 지불해야 하는 금액을 계산해 반환. 할인되지 않는 경우 가격을 그대로 반환하고, 가격에 대해 보너스 포인트 비율을 적용해 보너스 포인트 적립

- showCustomerInfo() : 고객 정보 출력(고객 이름, 등급, 현재 적립된 포인트)

 

새로운 고객 등급이 필요한 경우

ex) 단골 고객 -> 회사 매출에 많은 기여를 하는 우수 고객이라 좋은 혜택을 주고자 함 -> 우수 고객 등급은 VIP, 다음과 같은 혜택 제공

- 제품 구매 시 항상 10% 할인

- 보너스 포인트 5% 적립

- 담당 전문 상담원 배정

 

이 요구 사항을 어떻게 구현하면 좋을까?

- VIPCustomer 클래스를 따로 만들기

VIPCustomer.java

package com.day06;
//p.236
public class VIPCustomer { 
	//일반 고객(Customer.java)와 같은 속성 가짐(고객 아이디, 이름, 등급, 보너스 포인트, 적립 비율)
	private String custID, custName, custGrade; //고객 아이디, 고객 이름, 고객 등급
	private int bonusPoint; //보너스 포인트
	double bonusRatio; //보너스 포인트 적립 비율
	
	//VIP 고객들만 가지는 속성
	private int agentID; //전담 직원
	double saleRate; //일반 고객은 할인X, VIP고객만 10% 할인받을 수 있음
	
	public VIPCustomer() { //디폴트 생성자
		custGrade = "VIP"; //VIPCustomer의 기본 등급은 VIP
		bonusRatio = 0.05; //VIPCustomer의 기본 적립율 5%
		saleRate = 0.1; //VIPCustomer의 기본 할인율은 10%
	}
	
	public int calPrice(int price) {
		bonusPoint += price * bonusRatio;
		return (int)(price *(1 - saleRate)); //기본 고객과는 다르게 할인된 가격을 지불할 것이므로 게산 결과 할인 적용된 가격을 반환
	}
	
	public int getAgentID() { //해당 VIP 고객의 전담 직원 ID 알려줌
		return agentID;
	}
	
	public String showCustInfo() {
		return custName + "님의 등급은 " + custGrade + "이며, 보너스 포인트는 " + bonusPoint + "입니다.";
	}
}

 

OverridingTest.java

- 이제 일반 고객과 VIP 고객의 객체를 생성해서 실행해보자.

==> 채워넣기

package com.day06;
//p.252, 253 같이 넣을 것
public class OverridingTest {

	public static void main(String[] args) {
		//일반 고객 ID 10010, 이름 이순신 생성(객체 이름 : custLee)
		Customer custLee = new Customer(10010, "이순신");
		//이순신에게 초기 보너스 포인트 1000 부여
		custLee.bonusPoint = 1000;
				
		//VIP 고객 ID 10020, 이름 김유신, 전담 직원 ID 12345 생성(객체 이름 : custKim)
		VIPCustomer custKim = new VIPCustomer(10020, "김유신", 12345);
		//김유신에게 초기 보너스 포인트 10000 부여
		custKim.bonusPoint = 10000;
		
		int price = 10000; //위 고객들이 구매할 물건의 가격이 10000원이라고 해보자.
		//이순신이 지불해야 하는 금액 출력하기(계산은 이미 calPrice에서 했으므로 불러와서 쓰기) 
		System.out.println(custLee + "님이 지불해야 하는 금액은 " + custLee.calPrice(price) + "원 입니다.");
		//김유신이 지불해야 하는 금액 출력하기(계산은 이미 calPrice에서 했으므로 불러와서 쓰기)
		System.out.println(custLee + "님이 지불해야 하는 금액은 " + custKim.calPrice(price) + "원 입니다.");
		
		Customer vc = new VIPCustomer(10030, "나몰라", 2000);
		vc.bonusPoint = 1000;
		System.out.println(vc.custName + "님이 지불해야 하는 금액은 " + vc.calPrice(price) + "원 입니다.");
	}
}

==> 과제 : 오류나지 않게 생성자 만들고 상속 관계 만들기

 

728x90
728x90