Java

Java 기초(polymorphism)- AWS 풀스택 과정 51일차

awspspgh 2024. 10. 7. 18:20
목차
1. polymorphism
2. Date
3. Exception

 

1. polymorphism

■ 이론

이론 (1)

 

이론 (2)

 

▣ polymorphism01

package day06;

/* 객체지향 프로그램
 * - 프로그램 독립된 단위(객체)의 객체들을 모아서 관계를 맺어 처리하는 형태
 * - 각각의 객체는 메시지를 주고 받으면서 데이터를 처리
 * - 메시지를 받을 경우(매개변수를 통해) / 메시지를 주는 경우 (return)
 * - 추상화, 캡슐화(정보은닉), 상속, 다형성
 * 
 * - 추상화(Abstraction) - 핵심적인(공통적인) 코드만 보여주기
 * - 구현된 부분과 구현되지 않은 부분으로 분리
 * - 개인(자식)이 구현해야 할 부분은 분리하여 처리
 * 
 * - 캡슐화(Encapsulation) - 데이터 보호(정보은닉)
 * - 멤버변수(private)를 숨기는 형태, 메서드로 접근
 * - 멤버변수와 메서드를 하나로 묶어 처리하는 형태
 * - 은닉화 : 객체의 내부의 정보를 숨겨 외부로 드러나지 않게 보호하는 것
 * 
 * - 상속(Inheritance) - 코드 재사용(확장)
 * - 클래스를 상속받아 수정하면 중복 코드를 줄일 수 있음.
 * - 유지보수가 편함.
 * 
 * - 다형성(Polymorphism) - 객체 변환이 용이함.
 * - 하나의 코드가 여러 객체의 형태로 구현되어 실행되는 것
 * - 코드는 같은데 들어오는 객체에 따라 다른 실행결과를 얻을 수 있음.
 * - 다형성을 잘 활용하면 유연하고, 확장성있는, 유지보수가 편리한 프로그램을 만들 수 있음.
 */

class Animal{
	// 공통적인 속성
	public void move() {
		System.out.println("동물이 움직입니다.");
	}
}

class Human extends Animal {

	@Override
	public void move() {
		System.out.println("사람은 두 발로 걷습니다.");
	}
	public void readBook() {
		System.out.println("사람이 책을 읽습니다.");
	}
	
}

class Tiger extends Animal{

	@Override
	public void move() {
		System.out.println("호랑이가 네 발로 어슬렁거립니다.");
	}
	public void hunting() {
		System.out.println("호랑이가 사냥을 합니다.");
	}
	
}

class Eagle extends Animal{
	
	@Override
	public void move() {
		System.out.println("독수리가 하늘을 날아다닙니다.");
	}
	public void flying() {
		System.out.println("독수리가 날카로운 눈으로 날아다닙니다.");
	}
}

class Dog{
	public void move() {
		System.out.println("강아지가 아장아장 걷습니다.");
	}
}


public class Polymorphism01 {

	public static void main(String[] args) {
		// Human, Tiger, Eagle 객체 생성
		
		Human human = new Human();
		human.move();
		human.readBook();
		System.out.println("----------------");
		Tiger tiger = new Tiger();
		tiger.move();
		tiger.hunting();
		System.out.println("----------------");
		Eagle eagle = new Eagle();
		eagle.move();
		eagle.flying();
		
		System.out.println("--조상의 객체로 자식의 객체를 생성--");
		// 조상의 클래스로 자식의 객체를 생성 가능.
		// 조상에게 상속받은 메서드만 실행가능.
		// 자식객체로 부모객체의 생성은 불가능
//		Human h = new Animal(); // 불가능
		Animal hAnimal = new Human();
		hAnimal.move();
//		hAnimal.readBook(); // 사용불가능.
		Animal tAnimal = new Tiger();
		tAnimal.move();
		Animal eAnimal = new Eagle();
		eAnimal.move();

		System.out.println();
		System.out.println("--다형성 메서드 예시--");
		Polymorphism01 ex01 = new Polymorphism01();
		// 부모의 객체로 생성이 되었기 떄문에 당연히 가능
		ex01.moveAnimal(eAnimal);
		ex01.moveAnimal(tAnimal);
		ex01.moveAnimal(hAnimal);
		// 자신의 객체로 생성되었다 하더라도 자동 형변환이 이루어져 출력가능.
		ex01.moveAnimal(eagle);
		ex01.moveAnimal(tiger);
		ex01.moveAnimal(human);
		
		Dog dog = new Dog();
		dog.move();
		// animal 클래스를 상속받고 있지 않기 때문에 불가능.
		// ex01.moveAnimal(dog);
		
		System.out.println("-- Animal 배열 생성 예시 --");
		int cnt = 0;
		Animal[] aniList = new Animal[5];
		
		aniList[cnt] = hAnimal;
		cnt++;
		aniList[cnt] = tAnimal;
		cnt++;
		aniList[cnt] = eAnimal;
		cnt++;
		
		for(int i = 0; i < cnt; i++) {
			aniList[i].move();
		}
		
		System.out.println();
		System.out.println("-- 다운 케스팅 예시 --");
		
		// Human클래스 객체에 Animal을 상속받은 Human 클래스 객체를 다운 케스팅한 예시
		Human h = (Human)hAnimal;
		h.readBook();
		
//		Human h1 = (Human)tAnimal;
//		h1.readBook(); // casting 오류
		// instanceof 연산자로 확인하여 실행
		
		System.out.println();
		System.out.println("--instanceof 연산자--");
		// instanceof : 객체가 해당 클래스의 형이 맞는지 확인
		System.out.println(tAnimal instanceof Human);
		System.out.println(tAnimal instanceof Tiger);
		System.out.println(tAnimal instanceof Eagle);
		
		Animal downCastingTest = eAnimal;
		if(downCastingTest instanceof Human) {
//			((Human) downCastingText).readBook();
			Human testHuman = (Human) downCastingTest;
			testHuman.readBook();
		}else if(downCastingTest instanceof Tiger) {
			((Tiger) downCastingTest).hunting();
		}else if(downCastingTest instanceof Eagle) {
			((Eagle) downCastingTest).flying();
		}else {
			System.out.println("error");
		}
		
	}
	
	// 다향성 예시 메서드 (업케스팅 : 자동형변환 가능)
	public void moveAnimal(Animal animal) {
		animal.move();
		if(animal instanceof Human) {
			((Human) animal).readBook();
		}else if(animal instanceof Tiger) {
			((Tiger) animal).hunting();
		}else if(animal instanceof Eagle) {
			((Eagle) animal).flying();
		}else {
			System.out.println("error");
		}
	}
	
}

 

▷ 출력

출력 (1)

 

▣ CustomerMain

package day06;

/* Silver 고객 / Gold 고객(할인) / VIP 고객(할인)
 * - Silver 고객
 * 	=> 제품을 구매할 때 0% 할인 / 보너스 포인트 1% 적립
 * - Gold 고객
 * 	=> 제품을 구매할 때 10% 할인 / 보너스 포인트 2% 적립
 * - VIP 고객
 * 	=> 제품을 구매할 때 10% 할인 / 보너스 포인트 5% 적립
 * 	=> 전담 상담사
 * 
 * Customer / GoldCustomer / VIPCustomer 클래스 생성
 * GoldCustomer / VIPCustomer => Customer 클래스 상속
 */

public class CustomerMain {
	
	public static void main(String[] args) {
	// 업캐스팅 : 부모의 객체 배열에 자식 객체의 값을 넣을 수 있는 것은 업캐스팅이 가능하기 때문이다
	// 업캐스팅은 자동 형변환

	Customer[] customerList = new Customer[10];
	
	Customer cLee = new Customer(1001, "이정혁");
	Customer cHong = new Customer(1002, "홍길동");
	Customer cKim = new GoldCustomer(1003, "김철수");
	Customer cChoi = new GoldCustomer(1004, "최유진");
	int cnt = 0;
	
	customerList[cnt] = cLee;
	cnt++;
	customerList[cnt] = cHong;
	cnt++;
	customerList[cnt] = cKim;
	cnt++;
	customerList[cnt] = cChoi;
	cnt++;
	customerList[cnt] = new VIPCustomer(1005, "박영희", 1111);
	cnt++;
	customerList[cnt] = new VIPCustomer(1006, "김영수", 2222);
	cnt++;
	customerList[cnt] = new VIPCustomer(1007, "순이", 1111);
	cnt++;
	customerList[cnt] = new VIPCustomer(1008, "김영철", 2222);
	cnt++;
	
	System.out.println("-- 할인율과 포인트 계산 --");
	int price = 100000;
	// 모든 손님 대상
	// 홍길동님의 지불금액은 100000 / 포인트는 1000입니다.
	for(int i = 0; i < cnt; i++) {
		// 보너스 포인트 적립 => 금액 리턴
		int salePrice = customerList[i].calcPrice(price);
		System.out.println(customerList[i].getCustomerName() + "님의 지불금액은 " + salePrice + " / 포인트 " + customerList[i].getBonusPoint());
		System.out.println("--------------------");
	}
	
	// 다운캐스팅 : 부모의 공유되는 멤버변수나 메서드가 아닌
	// 자식 고유의 멤버변수나 메서드를 호출하고자 할 경우 사용
	// 다운캐스팅시 반드시 명시적으로 형변환 해야함.
	// agentID = 1111 => 3333 변경
	System.out.println("-------------");
	for(int i = 0; i < cnt; i++) {
		Customer c = customerList[i];
		if(c instanceof VIPCustomer) {
			VIPCustomer vip = (VIPCustomer)c;
			if(vip.getAgentID() == 1111) {
				vip.setAgentID(3333);			
				customerList[i].customerInfo();
			}
		}
	}
	
	// 고객 정보 출력
	for(int i = 0; i < cnt; i++) {
		customerList[i].customerInfo();
	}
	
	
	
	}
}

 

▣ Customer

package day06;

import java.util.Scanner;

/* customerID : 고객ID
 * customerName : 고객이름
 * customerGrade : 고객등급
 * bonusPoint
 * bonusRatio : 0.01 => 1%
 * 
 * 기본 customerGrade = Silver
 * 
 * 메서드
 * 1. 보너스 적립 계산 메서드
 * 	=> 구매 금액을 주고 적립 보너스를 계산하여 bonusPoint 누적
 * 	=> 보너스 적립, 할인여부를 체크하여 구매금액을 리턴
 * 
 * 2. 출력
 * 	=> 홍길동님은 VIP등급이며, 보너스 포인트는 5000점입니다.
 * 	   전담 상담사 번호는 1111입니다. <- VIP만 추가 (agentID) 
 */
public class Customer {

	protected int customerID;
	protected String customerName;
	protected String customerGrade;
	protected int bonusPoint;
	protected double bonusRatio;
	
	// 생성자
	public Customer() {}
	public Customer(int customerID, String customerName) {
		this.customerID = customerID;
		this.customerName = customerName;
		customerGrade = "Silver";
		bonusRatio = 0.01;
	}
	
	// 메서드
	// 가격 매개변수로 받아 => 포인트 적립, 할인가격 리턴
	public int calcPrice(int price) {
		bonusPoint += (int)(price * bonusRatio);
		return price; // Silver등급은 할인이 없음.
	}
	
	// 출력메서드
	/* 홍길동님은 VIP등급이며, 보너스 포인트는 5000점입니다.
	 * 전담 상담사 번호는 1111입니다. <- VIP만 추가 (agentID) 
	 */
	public void customerInfo() {
		System.out.println(customerName + "님은 " + customerGrade + "등급이며, 보너스 포인트는 " + bonusPoint + "점 입니다.");
	}
	
	// getter & setter
	public int getCustomerID() {
		return customerID;
	}
	public void setCustomerID(int customerID) {
		this.customerID = customerID;
	}
	public String getCustomerName() {
		return customerName;
	}
	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}
	public String getCustomerGrade() {
		return customerGrade;
	}
	public void setCustomerGrade(String customerGrade) {
		this.customerGrade = customerGrade;
	}
	public int getBonusPoint() {
		return bonusPoint;
	}
	public void setBonusPoint(int bonusPoint) {
		this.bonusPoint = bonusPoint;
	}
	public double getBonusRatio() {
		return bonusRatio;
	}
	public void setBonusRatio(double bonusRatio) {
		this.bonusRatio = bonusRatio;
	}
	
	@Override
	public String toString() {
		return "Customer [customerID=" + customerID + ", customerName=" + customerName + ", customerGrade="
				+ customerGrade + ", bonusPoint=" + bonusPoint + ", bonusRatio=" + bonusRatio + "]";
	}
	
}

 

▣ GoldCustomer

package day06;

public class GoldCustomer extends Customer{
	private double saleRatio; //할인율 Gold, VIP만 존재
	
	public GoldCustomer() {}
	// => 제품을 구매할 때 10% 할인 / 보너스 포인트 2% 적립
	public GoldCustomer(int id, String name) {
		super(id, name);
		customerGrade = "Gold";
		bonusRatio = 0.02;
		saleRatio = 0.1;
	}
	
	// 할인금액 리턴이 필요한 calcPrice 오버라이딩
	@Override
	public int calcPrice(int price) {
		bonusPoint += (int)(price * bonusRatio);
		return price - (int)(price * saleRatio);
	}
	
	public double getSaleRatio() {
		return saleRatio;
	}
	public void setSaleRatio(double saleRatio) {
		this.saleRatio = saleRatio;
	}
	
}

 

▣ VIPCustomer

package day06;

public class VIPCustomer extends Customer{
	private double saleRatio; // 할인율 Gold, VIP만 존재
	private int agentID; // VIP만 존재
	
	public VIPCustomer() {}
	public VIPCustomer(int id, String name, int agentid) {
		super(id, name);
		customerGrade = "VIP";
		bonusRatio = 0.05;
		saleRatio = 01.;
		agentID = agentid;
	}
	// 할인금액 리턴이 필요한 calcPrice 오버라이딩
	@Override
	public int calcPrice(int price) {
		bonusPoint += (int)(price * bonusRatio);
		return price - (int)(price * saleRatio);
	}
	@Override
	public void customerInfo() {
		// TODO Auto-generated method stub
		super.customerInfo();
		System.out.println("담당 상담원 번호는 " + agentID + "입니다.");
	}
	
	public double getSaleRatio() {
		return saleRatio;
	}
	public void setSaleRatio(double saleRatio) {
		this.saleRatio = saleRatio;
	}
	public int getAgentID() {
		return agentID;
	}
	public void setAgentID(int agentID) {
		this.agentID = agentID;
	}
		
}

 

▷ 출력

출력 (2)

 

2. Date

▣ Date01

package day06;

import java.util.Calendar;
import java.util.Date;

public class Date01 {

	public static void main(String[] args) {
		/* 날짜 / 시간 클래스
		 * Date 클래스 => Deprecated(비권장)
		 * Calendar => Date 후속작, 추상클래스 => 객체를 생성할 수 없음.
		 * new 키워드로 객체 생성이 불가능
		 * getInstance() 메서드를 이요하여 객체를 얻어 옴 
		 */
		
		Date d = new Date();
		System.out.println(d);
//		d.getDate();
		Calendar c = Calendar.getInstance(); // 오늘 날짜
		System.out.println(c);
		System.out.println("---------------");
		// month 0 ~ 11 +1 표현
		int year = c.get(Calendar.YEAR);
		System.out.println(year);
		int month = c.get(Calendar.MONTH) + 1;
		System.out.println(month);
		int day = c.get(Calendar.DAY_OF_MONTH);
		System.out.println(day);
		int week = c.get(Calendar.DAY_OF_WEEK);
		int hour = c.get(Calendar.HOUR);
		int minute = c.get(Calendar.MINUTE);
		int AmPm = c.get(Calendar.AM_PM);
		// 일 = 1...
		System.out.println(week);
		System.out.println(year+"-"+month+"-"+day);
		
		// 2024-10-7(월) 오후 3:51
		int num = c.get(Calendar.DAY_OF_WEEK_IN_MONTH);
		char sun = ' ';
		String am_pm = AmPm == 1 ? "오후" : "오전";
		switch(num) {
		case 1: sun = '월'; break;
		case 2: sun = '화'; break;
		case 3: sun = '수'; break;
		case 4: sun = '목'; break;
		case 5: sun = '금'; break;
		case 6: sun = '토'; break;
		case 7: sun = '일'; break;
		default: System.out.println("error");
			
		}
		System.out.println(year+"-"+month+"-"+day+"("+sun+") "+am_pm+" "+hour+":"+minute);
		
		
		
	}

}

 

▷ 출력

출력 (1) 뒷 부분 생략

 

▣ Date02

package day06;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Date02 {

	public static void main(String[] args) {
		// LocalDateTime
		LocalDateTime today = LocalDateTime.now();
		System.out.println(today);
		System.out.println(today.getYear());
		String t = today.toString();
		System.out.println(t);
		String date = t.substring(0, t.indexOf("T"));
		System.out.println(date);
		String hms = t.substring(t.indexOf("T")+1, t.indexOf("."));
		System.out.println(hms);
		
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
		System.out.println(dtf.format(today));
		
		LocalDateTime date1 = LocalDateTime.of(2005,1,1,8,30);
		System.out.println(date1.format(dtf));

	}

}

 

▷ 출력

출력 (2)

 

▣ Date03

package day06;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Date03 {

	public static void main(String[] args) throws ParseException {
		Date date = new Date();
		System.out.println(date);
		// yyyy-MM-dd(E) hh:mm:ss
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd(E) hh:mm:ss");
		// String 형식으로 변경
		System.out.println(sdf.format(date));

		// 날짜 모양의 문자열을 => Date로 변경
		String dateStr = "2024-10-07(월) 04:48:00";
		Date date2 = null;
		try {
			date2 = sdf.parse(dateStr);
			System.out.println(date2);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

 

▷ 출력

출력 (3)

 

3. Exception

■ 이론

에러 (1)

 

▣ Exception01

package day06;

public class Exception01 {

	public static void main(String[] args) {
		// RuntimeException : 실행 예외 클래스
		/* Exception : 예외
		 * 개발자가 코드 구현시 발생할 수 있는 에러를 예외
		 * 예외처리 : 예외를 개발자가 처리하는 구문
		 * 예외가 발생하면 예외 발생 시점부터 코드는 중지 => 예외문구 출력
		 * 예외처리 => 예외가 발생할 수 있는 값만을 빼고, 나머지는 정상처리로 유지시키기위한 기능
		 * try ~ catch
		 * try ~ catch ~ finally
		 * try : 예외가 발생할 가능성이 있는 구문 작성
		 * catch : try 구문에서 발생한 예외를 처리
		 * finally : try 구문과 상관없이 반드시 처리되어야 하는 구문을 작성 (생략가능)
		 */

		try {
			System.out.println(1);
			System.out.println(2);
			System.out.println(1/0); // ArithmeticException
		} catch (Exception e) {
			e.printStackTrace(); // 실제 예외구문을 콘솔에 출력
			System.out.println("예외가 발생했습니다.~!!");
		} finally {			
			System.out.println(4);
			System.out.println(5);
			System.out.println(6);
			System.out.println(7);			
		}
		
	}

}

 

▷ 출력

출력 (1)

 

▣ Exception02

package day06;

public class Exception02 {

	public static void main(String[] args) {
		// ArithmeticException : 0으로 나누었을 때 발생하는 Exception
		// 1 2 +   1 2 -   1 2 *   1 0 /  1 0 %
		
		Exception02 ex02 = new Exception02();
		System.out.println(ex02.calc(1, 0, '/'));
		
//		try {
//			//예외가 발생할 수 있는 구문 작성
//			System.out.println(ex02.calc(1, 2, '+'));
//			System.out.println(ex02.calc(1, 2, '-'));
//			System.out.println(ex02.calc(1, 2, '*'));
//			System.out.println(ex02.calc(1, 0, '/'));
//		} catch (Exception e) {
//			// 예외 처리 작성
//			e.printStackTrace();
//			System.out.println(e.getMessage());
//		}
		
		System.out.println(ex02.calc(1, 2, '-'));

	}
	
	// 두수를 입력받고, 연산자를 입력받아 4칙연산의 결과를 리턴하는 메서드
	// 매개변수 : int num1, int num2, char op
	// return Type : double
	// 예외 발생시키기 : throw new 발생시킬 수 있음.
	// 예외를 발생시키게 되면 메서드 선언부 끝에 throws를 적고, 발생시킨 예외를
	// 반드시 적어줘야 함.
	// throws는 예외적으로 RuntimeException만 생략가능
	// throws : 예외 떠넘기기
	public double calc(int num1, int num2, char op) throws RuntimeException {
		double res = 0;
		
		//연산자가 / % 인경우 num2 가 0이면 예외 발생시키기
		if((op == '/' || op == '%') && num2 == 0) {
			throw new RuntimeException("num2는 0이 될 수 없습니다.");
		}
		
		switch(op) {
		case '+' : res = num1 + num2; break;
		case '-' : res = num1 - num2; break;
		case '*' : res = num1 * num2; break;
		case '/' : res = num1 / num2; break;
		case '%' : res = num1 % num2; break;
		default : 
			//예외발생
			throw new RuntimeException(op+"는 산술연산자가 아닙니다.");
		}
		return res;
	}

}

 

▷ 출력

출력 (2) ctrl + F11

 

▣ Exception03

package day06;

public class Exception03 {

	public static void main(String[] args) {
		/* 자주 발생하는 예외 코드들
		 * ArithmeticException : 0으로 나누었을 때 발생
		 * ArrayIndexOutOfBoundsException : 배열의 index가 범위를 벗어났을 때 발생
		 * NullPointerException : 객체의 값이 null일 경우, 혹은 객체 자체가 없을 경우
		 * ClassCastException : 다운 캐스팅이 잘못 되었을 경우
		 */
		
//		int arr[] = null;
		int arr[] = new int[5];
		for(int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}

	}

}

 

▷ 출력

출력 (3)