프로그래밍/수업일지 (39)

728x90

 

수업내용 정리 (Java)

 

1. 테스트

더보기
// 문제
public static void main(String[] args) {
	System.out.println("1번");
	operation(10,3);
	//덧셈 결과: 13
	//뺄셈 결과: 7
	//곱셈 결과: 30
	//몫 결과: 3
	//나머지 결과: 1
	
	System.out.println("\n2번");
	abs(10, 3);	//두 수 차의 절대값(거리의 개념): 7
	abs(3, 10);	//두 수 차의 절대값: 7
	
   	System.out.println("\n3번");
	System.out.println("원 둘레: "+cirRound(2.4));	//반지름
	// 원 둘레: (반지름*2)*3.14 / Math.PI
	System.out.println("원 넓이: "+cirArea(2.4));
	// 원 넓이: (반지름*반지름)*3.14
	
	System.out.println("\n4번");
	for(int i=2; i<11; i++) {
		if(isEven(i)) {	// 짝수 2,4,6,8,10
			System.out.println("숫자 "+i+"는 짝수입니다.");
		}
	}
}
결과 출력

 

 

// 1번
private static void operation(int i, int j) {
	System.out.println(i+" + "+j+" = "+(i+j));
	System.out.println(i+" - "+j+" = "+(i-j));
	System.out.println(i+" * "+j+" = "+(i*j));
	System.out.println(i+" / "+j+" = "+(i/j));
	System.out.println(i+" % "+j+" = "+(i%j));
}
  • 간단한 연산자를 출력할 때 sysout에 바로 계산해도 되지만(ex: i+j) 다른 문자와 연결하여 사용할 때는 소괄호()로 묶어서 사용해야 한다.

 

// 2번
private static void abs(int i, int j) {
	if(i>j) {
		System.out.println(i+", "+j+"의 절대값: "+(i-j));
	}else {
		System.out.println(i+", "+j+"의 절대값: "+(j-i));
	}
}
  • 절대값(두 수의 거리)은 음수값이 나오면 안 되기 때문에 if문으로 i가 j보다 작을 경우를 걸러준다.

 

// 3번
private static double cirRound(double d) {
	return d*2*Math.PI;;
}

private static double cirArea(double d) {
	double a = d*d*Math.PI;
	return a;
}
  • return에 값을 바로 반환하거나 임시변수에 값을 저장해서 임시변수를 반환할 수 있다.

 

// 4번
private static boolean isEven(int i) {
	if(i%2 == 0) {
		return true;
	}
	return false;	// return문이 있을때는 else가 없어도 됨
		// return i%2 == 0 도 되긴 하나 비추
}
  • return문일 때는 else가 없어도 된다. (if에서 바로 return하면 되기 때문에)
  • return i%2 == 0 이런 코드도 가능하지만 비추천!

 

2. 추상 클래스 (참고)

  • 하나 이상의 추상 메소드를 포함하는 클래스
  • 반드시 사용할 메소드는 추상 클래스에서 추상 메소드로 선언해두면 이 클래스를 상속하는 모든 클래스가 추상 클래스 내에 있는 모든 메소드를 반드시 재정의(오버라이딩)를 해야 한다.
  • 추상 메소드: 선언부만 남기고 바디를 날린, 동작이 존재하지 않는 메소드
  • public abstract를 붙이지 않아도 붙어있는 것과 동일하게 작동된다.
  • 인터페이스도 일종의 추상 클래스라고 볼 수 있다. (추상 클래스보다 추상화 정도가 높다.)
더보기
public class Ex02 {
	public static void main(String[] args) {
		Print p = new PrintImpl();
		p.printMonitor();
		p.printPaper();
		p.getMonitor();
		p.getPager();
		
	}//end main -> 프로그램 종료
}
  • 컨트롤 타워 (업무 지시만 하는 클래스)

 

public interface Print {
	public abstract void printPaper();
	public abstract void printMonitor();
	String getPager();
	public String getMonitor();	// 권장!
}
  • 인터페이스는 다른 클래스들의 기본 틀이 되는 클래스다.
  • public abstract void를 작성하지 않아도 정상작동하지만, public은 작성하는 것을 권장한다.
  • 정상작동하는 여러가지 방법을 통해 추상 메소드를 작성했다.

 

public class PrintImpl implements Print {
	@Override
	public void printPaper() {
		System.out.println("종이출력");
	}

	@Override
	public void printMonitor() {
		System.out.println("화면출력");
	}

	@Override
	public String getPager() {
		return "종이";
	}

	@Override
	public String getMonitor() {
		return "화면";
	}
}
  • 인터페이스를 상속할 때는 상속이 아닌 구현이라고 한다.
  • 추상 메소드를 오버라이딩해서 동작을 작성했다.

 

 

3. 예제

더보기
public class CalcMain {

	public static void main(String[] args) {
		int num1 = 10;
		int num2 = 3;
		Calc c = new CompleteCalc();
		System.out.println(c.add(num1, num2));
		System.out.println(c.substract(num1, num2));
		System.out.println(c.time(num1, num2));
		System.out.println(c.divide(num1, num2));
		
		//1
		((CompleteCalc)c).divide(num1, num2);
		//2
		CompleteCalc c2 = new CompleteCalc();
		c2.divide(num1, num2);
	}
}
  • 1은 강제형변환, 2는 새로 객체를 만들어서 사용한 코드

 

public interface Calc {
	public final static double PI = 3.14;
	int ERROR = -999999999, OK = 200;
	
	public int add(int num1, int num2);
	public int substract(int num1, int num2);
	public int time(int num1, int num2);
	public int divide(int num1, int num2);
	
	// 인터페이스에 선언된 변수는 무조건 final 변수
}
  • 인터페이스에 선언된 변수는 무조건 final 변수이기 때문에, public final static 까지는 적지 않아도 자동 적용된다.
  • 파이값은 이미 Math.PI로 코드가 있지만 임의로 작성했다.

 

public class Calculator implements Calc {

	@Override
	public int add(int num1, int num2) {
		return num1 + num2;
	}

	@Override
	public int substract(int num1, int num2) {
		return num1 - num2;
	}

	@Override
	public int time(int num1, int num2) {
		return num1 * num2;
	}

	@Override
	public int divide(int num1, int num2) {
		return num1 / num2;
	}
}
  • 인터페이스 Calc를 구현하는 클래스
  • 이렇게만 하면 num1, num2 중 0이 들어가면 divide 메소드에서 오류가 난다.

 

public class CompleteCalc extends Calculator{

	@Override
	public int divide(int num1, int num2) {
		if(num1 == 0 || num2 == 0) {
			return ERROR;	// -9999999
		}
		return num1/num2;
	}
	public void showInpo() {
		System.out.println("나눗셈 개선");
	}
}
  • 인터페이스 Calc를 구현하는 클래스2
  • 위의 클래스에서 오류가 나는 메소드를 개선하기 위해 만들었다. (해당 클래스에서 바로 만들어도 되지만 다른 사람이 나와 동시에 코드를 작성하고 더 나은 코드를 사용할 때 등을 위해서)

 

 

4. try-catch, throw / 예외처리 (참고1 / 참고2)

  • 에러 발생 시 프로그램을 종료시키지 않고 예외처리를 통해 정상작동하게 만들어 준다.
  • try와 catch는 한 몸으로 떨어져선 안 된다.
  • try 블록에서 예외가 발생할 수 있는 코드를 넣고, 예외가 발생되지 않았을 경우엔 catch 블록의 코드는 실행되지 않고 스킵된다.
  • try 블록에서 예외가 발생될 경우엔 실행을 멈추고 catch 블록으로 이동하여 예외처리 코드를 실행한다.
  • try, catch 블록은 무조건 하나씩 있어야 하지만, catch 블록은 하나 이상 있을 수 있다.
  • throw를 통해 예외를 던져 고의로 예외를 발생시킬 수 있다.
  • try에서 던진(throw를) catch에서 받는다.
더보기
try {
	String str = null;
	int len=str.length();
} catch (NullPointerException e) {
	System.out.println(e.getMessage());
	System.out.println("null포인터 예외 발생");
	e.printStackTrace();
}
  • try 블록에서 str 변수에 null 값을 넣어 str.length에 예외를 발생시켰다.
  • catch의 괄호에는 예외타입과 참조변수를 입력한다.
  • 예외 발생 시 발생 예외에 해당하는 클래스의 인스턴스가 만들어진다.
  • getMessage()의 경우 발생한 예외에 대한 기본 정보를 제공해준다. (간단)
  • printStackTrace()의 경우 자세한 예외 정보, 예외가 발생한 위치를 제공해준다.

 

try {
	int[] arr1 = new int[3];
	arr1[-1]=20;
} catch (ArrayIndexOutOfBoundsException e) {
	System.out.println(e.getMessage());
	System.out.println("인덱스 예외 발생");
	e.printStackTrace();
}

 

 4-1) 예제 ㄱ 

더보기
import java.io.IOException;
import java.util.Scanner;

public class ExceptionMain {
	public static void main(String[] args) {
		System.out.print("나이입력> ");
		try {
			int age = readAge();
			System.out.println("당신은 "+age+"세입니다.");
		} catch (AgeInputException e) {
			System.out.println(e.getMessage());
		} catch(IOException e) {
			System.out.println(e.getMessage());
			System.out.println("입출력 예외 발생");
		}
	}

	private static int readAge() throws AgeInputException, IOException{	//예외 여러개 사용 가능
		Scanner keyboard = new Scanner(System.in);
		int age = keyboard.nextInt();
		if(age < 0) {
//			AgeInputException excpt = new AgeInputException();
//			throw excpt;
			throw new AgeInputException();	//위 두 줄과 동일함
//			throw new IOException();
		}
		return age;
	}
}
// 프로그래머 정의 예외 클래스
public class AgeInputException extends Exception{
	public AgeInputException() {
		super("유효하지 않는 나이가 입력되었습니다.");
	}
}
  • 나이 입력에서 바로 try-catch를 통해 예외 상황을 만들어 해당하는 경우에는 throw를 통해 강제로 catch에 던진다.
  • 예외 상황에 해당하지 않는 경우엔 입력받은 값을 그대로 반환한다.

 


 

질문한 내용이나 어려웠던 점 메모

1. try-catch, throw

  • 처음엔 이해한듯 했는데 예제에서 throws(예외 여러개 사용 가능) 부분부터 헷갈린다. 우선 이해하려면 오래 걸릴 것 같아서 여러번 사용해보고 따라하면서 응용도 해봐야 객체마냥 자연스럽게 이해할 수 있을듯 싶어서 일단 머리에 집어넣기로 했다..

 


 

전체 피드백

  • try-catch, throw 여러번 사용해보기!

 


728x90
728x90

 

수업내용 정리 (Java)

 

1. PhoneBook

 1-1) Main ㄱ 

더보기
package controller;

import java.util.Scanner;

public class Main {
	public static Scanner sc = new Scanner(System.in);
	
	public static void main(String[] args) {
		PhoneBookManager manager = new PhoneBookManager();
		
		while(true) {
			showMenu();
			int menu = sc.nextInt();
			System.out.println();
			switch(menu) {
			case 1:
				System.out.println("===> 전화번호 입력");
                showSub();
				System.out.print("메뉴선택> ");
				manager.inputData(sc.nextInt());
				break;
			case 2:
				System.out.println("===> 전화번호 검색");
				manager.serchData();
				break;
			case 3:
				System.out.println("===> 전화번호 수정");
				manager.correctionData();
				break;
			case 4:
				System.out.println("===> 전화번호 삭제");
				manager.deletData();	// 아직 안 햇음
				break;
			case 5:
				System.out.println("===> 전체 목록");
				manager.showAllData();
				break;
			case 0:
				System.out.println(" > 프로그램을 종료합니다.");
				return;	// 값을 반환하면서 while 문을 나간다.
			default:
			}
			System.out.println();
		}
		
	}

	private static void showMenu() {
		System.out.println("===== 전화번호부 =====");
		System.out.println("""
				------------------
				 1. 전화번호 입력
				 2. 전화번호 검색
				 3. 전화번호 수정
				 4. 전화번호 삭제
				 5. 전체 목록 출력
				 0. 프로그램 종료
				------------------ """);
		System.out.print("메뉴선택> ");
	}
	private static void showSub() {
		System.out.println("""
				------------------
				 1. 일반
				 2. 대학
				 3. 회사
				 > 다른 번호 입력 시 메인으로 돌아갑니다.
				------------------ """);
		System.out.print("메뉴선택> ");
	}
}
  • 클래스를 배우면서 메인은 간소화하고 manager이라는 클래스를 만들어 메소드를 저장해 사용하는 방법을 배웠다.
  • 메뉴도 while문 밖에서 메인 클래스의 메소드로 작성해서 메인 메소드를 간단화했다.
  • 처음에는 전화번호 입력, 전체 출력, 프로그램 종료만 했다가 조금씩 추가해서 총 6개의 메뉴가 생겼다.
  • 15일차에 배웠던 텍스트 블록을 응용해서 메뉴 선택을 작성해봤다.

 

 1-2) PhoneInfo ㄱ 

더보기
package bean;

public class PhoneInfo {
	private String name;
	private String phoneNum;
	private String birth;
	
	// 생성자
	public PhoneInfo(String name, String phoneNum, String birth) {
		this.name = name;
		this.phoneNum = phoneNum;
		this.birth = birth;
	}
	public PhoneInfo(String name, String phoneNum) {
		this.name = name;
		this.phoneNum = phoneNum;
	}
	
	// 메소드
	public void showPhoneInfo(){
		System.out.println(" ▸ 이름\t\t: "+name);
		System.out.println(" ▸ 전화번호\t: "+phoneNum);
		if(birth!=null)
			System.out.println(" ▸ 생일\t\t: "+birth);
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setPhoneNum(String phoneNum) {
		this.phoneNum = phoneNum;
	}
    
	@Override
	public String toString() {
		String str = " ▸ 이름\t\t: "+name+"\n ▸ 전화번호\t: "+phoneNum;
		if(birth!=null)
			str += "\n ▸ 생일\t\t: "+birth;
		return str;
	}
}
  • 일반 클래스
  • 대학, 회사 클래스의 부모클래스가 되는 클래스
  • showPhoneInfo 메소드로 정보를 출력하지만 toString 메소드를 오버라이딩해서 사용하는 방법도 연습 겸 사용해봤다.

 

 1-3) PhoneUnivInfo ㄱ 

더보기
package bean;

public class PhoneUnivInfo extends PhoneInfo {
	private String major;
	private int year;
	
	public PhoneUnivInfo(String name, String phoneNum, String major, int year) {
		super(name, phoneNum);
		this.major = major;
		this.year = year;
	}
	public PhoneUnivInfo(String name, String phoneNum, String birth, String major, int year) {
		super(name, phoneNum, birth);
		this.major = major;
		this.year = year;
	}

	public String getMajor() {
		return major;
	}
	public void setMajor(String major) {
		this.major = major;
	}
    
	@Override
	public void showPhoneInfo() {
		super.showPhoneInfo();
		System.out.println(" ▸ 전공\t\t: "+major);
		System.out.println(" ▸ 학년\t\t: "+year);
	}
	@Override
	public String toString() {
		String str = (super.toString())+"\n ▸ 전공\t\t: "+major+"\n ▸ 학년\t\t: "+year;
		return str;
	}
}
  • 대학 클래스 (자식 클래스)
  • 부모클래스로 PhoneInfo 클래스(일반)를 상속한다.
  • 부모클래스에서 갖고있는 필드, 생성자, 메소드가 보이진 않지만 존재한다.
  • 부모클래스에서 갖고있는 생성자에 추가하여 사용하려면 부모클래스에 있는 클래스와 같은 형식의 생성자를 만들고, 매개변수를 추가하여 사용한다.
  • 부모클래스에 있는 필드를 저장하려고 매개변수로 받아온 값은 super();을 통해 저장할 수 있다.
  • 부모클래스의 메소드에 추가하여 사용하려면 부모클래스에 있는 메소드를 오버라이딩하면 된다.
  • super();을 통해 부모클래스의 메소드를 가져오고 추가로 행할 코드를 밑에 작성하면 부모클래스의 메소드와 추가로 행할 코드가 같이 동작한다.

 

 1-4) PhoneCompanyInfo ㄱ

더보기
package bean;

public class PhoneCompanyInfo extends PhoneInfo {
	private String company;
	
	public PhoneCompanyInfo(String name, String phoneNum, String company) {
		super(name, phoneNum);
		this.company = company;
	}
	public PhoneCompanyInfo(String name, String phoneNum, String birth, String company) {
		super(name, phoneNum, birth);
		this.company = company;
	}
    
	@Override
	public void showPhoneInfo() {
		super.showPhoneInfo();
		System.out.println(" ▸ 회사\t\t: "+company);
	}
	@Override
	public String toString() {
		String str = (super.toString())+"\n ▸ 회사\t\t: "+company;
		return str;
	}
}
  • 회사 클래스 (자식 클래스)
  • 부모클래스로 PhoneInfo 클래스(일반)를 상속한다.
  • 부모클래스인 일반 클래스를 상속하고 있기 때문에 (같은 부모를 상속하고 있는)대학 클래스와는 상관없이 일반 클래스에서만 가져올 수 있다.

 

 1-5) PhoneBookManager ㄱ

더보기
  • manager

 

package controller;

import bean.PhoneInfo;
import bean.PhoneUnivInfo;
import bean.PhoneCompanyInfo;
  • import

 

private PhoneInfo[] phoneList  = new PhoneInfo[100];
private int cnt = 0;	//index와 목록 개수
private int a;
private String name;
private String phoneNum;
private String birth;
  • 필드 값

 

public PhoneBookManager(int size) {
	cnt = 0;
	this.phoneList = new PhoneInfo[size];
}
  • 생성자

 

public void inputData() {
	System.out.println();
	switch(sub) {
	case 1:
		nomalInputData();
		break;
		
	case 2:
		uivInputData();
		break;
		
	case 3:
		compInputData();
		break;
		
	default:
	}
}
  • Main의 case 1에 해당하는 메소드
  • Main에서 switch를 사용해 메뉴를 만들었기 때문에 여기서도 switch를 사용하기로 했다.
  • 일반, 대학, 회사. 선택에 따라 저장할 값이 다르기 때문에 메소드를 따로 만들었다.

 

private void data() {
	birth = null;
	System.out.print(" 이름 입력> ");
	name = Main.sc.next();
	System.out.print(" 전화번호 입력> ");
	phoneNum = Main.sc.next();
	System.out.print(" 생일을 입력하시겠습니까?\n(Y/y)> ");
	String Y = Main.sc.next();
	if(Y.equals("Y") || Y.equals("y")) {
		System.out.print(" 생년월일 입력> ");
		birth = Main.sc.next();
	}
}
  • inputData에서 값을 저장하기 위해 공통으로 사용할 코드
  • Scanner는 Main이 import 해왔기 때문에 같은 패키지 소속인 PhoneBookManager이 Main을 언급하며 사용할 수 있다.  ex) Main.sc.next();
  • birth는 입력하지 않을 수 있기 때문에 초반에 값을 null로 지워주고 name, phoneNum, 상황에 따라 birth를 입력받는다.

 

private void nomalInputData() {
	System.out.println(" -> 일반");
	data();
	if(birth == null) {
		PhoneInfo info = new PhoneInfo(name, phoneNum);
		phoneList[cnt++] = info;
	}else {
		PhoneInfo info = new PhoneInfo(name, phoneNum, birth);
		phoneList[cnt++] = info;	//++cnt 는 전치라서 카운트를 먼저 하고 저장함
	}
}
  • inputData에서 일반 선택 시
  • data 메소드를 사용하여 name, phoneNum, (상황에 따라)birth 값을 새로 저장하고 if문을 통해 birth가 null값인지 아닌지 구분함에 따라 생성자를 사용하여 저장한다.

 

private void uivInputData() {
	System.out.println(" -> 대학");
	data();
	System.out.print(" 전공 입력> ");
	String major = Main.sc.next();
	System.out.print(" 학년 입력> ");
	int year = Main.sc.nextInt();
	if(birth == null) {
		PhoneInfo info = new PhoneUnivInfo(name, phoneNum, major, year);
		phoneList[cnt++] = info;
	}else {
		PhoneInfo info = new PhoneUnivInfo(name, phoneNum, birth, major, year);
		phoneList[cnt++] = info;
	}
}
  • inputData에서 대학 선택 시
  • nomalInputData 메소드를 기본 틀로 잡고 추가로 major, year을 입력받아 저장한다.

 

private void compInputData() {
	System.out.println(" -> 회사");
	data();
	System.out.print(" 회사 입력> ");
	String company = Main.sc.next();
	if(birth == null) {
		PhoneInfo info = new PhoneCompanyInfo(name, phoneNum, company);
		phoneList[cnt++] = info;
	}else {
		PhoneInfo info = new PhoneCompanyInfo(name, phoneNum, birth, company);
		phoneList[cnt++] = info;
	}
}
  • inputData에서 회사 선택 시
  • nomalInputData 메소드를 기본 틀로 잡고 추가로 company를 입력받아 저장한다.

 

public void showAllData() {
	System.out.println("----------------");
	for(int i=0; i<cnt; i++) {
		phoneList[i].showPhoneInfo();
		System.out.println("----------------");
	}
}
  • phoneList에 저장한 모든 값을 출력하는 메소드
  • 출력은 phoneInfo 클래스의 메소드를 사용했다.

 

private int searchIdx(String name) {
	a = -1;
	for(int i=0; i<cnt; i++) {
		if(name.equals(phoneList[i].getName())) {
			a = i;
            break;
		}
	}
	return a;
}
  • 검색, 수정, 삭제에서 사용할 코드를 줄이기 위해 만든 메소드
  • a의 값을 -1로 지워준다.
  • 입력받은 name과 동일한 name이 있는지 검색해서 있으면 a에 값을 저장하고 a 값을 return한다.

 

public void serchData() {
	System.out.print(" 검색할 이름> ");
	String name = Main.sc.next();
	int idx = searchIdx(name);
	if(idx == -1) {
		System.out.println(" > 정보를 찾을 수 없습니다.");
	}else {
		phoneList[idx].showPhoneInfo();
	}
}
  • Main에서 case 2에 해당하는 메소드
  • 검색할 이름을 입력받고, searchIdx 메소드를 사용해 a값을 새로운 변수 idx에 저장한다.
  • idx 값이 -1일 경우 정보를 찾을 수 없다는 메소드를 사용하고, -1이 아닐 경우 idx 값에 해당하는 phoneList 인덱스를 출력한다.

 

public void correctionData() {
	System.out.print(" 수정할 이름> ");
	String name = Main.sc.next();
	
	int idx = searchIdx(name);
	if(idx == -1) {
		System.out.println(" > 정보를 찾을 수 없습니다.");
	}else {
		phoneList[idx].showPhoneInfo();
		System.out.print(" 수정할 이름 입력> ");
		phoneList[idx].setName(Main.sc.next());
		System.out.print(" 수정할 전화번호 입력> ");
		phoneList[idx].setPhoneNum(Main.sc.next());
		System.out.println(" > 정보 수정이 완료되었습니다.");
	}
}
  • Main에서 case 3에 해당하는 메소드
  • 수정할 이름을 입력받고, idx 값이 -1이 아닐 경우 이름과 전화번호를 수정받는다.

 

public void deletData() {
	System.out.print(" 삭제할 이름> ");
	String name = Main.sc.next();
	int idx = searchIdx(name);
	if(idx == -1) {
		System.out.println(" > 정보를 찾을 수 없습니다.");
	}else {
		phoneList[idx].showPhoneInfo();
		for(int i=idx; i<cnt-1; i++) {
			phoneList[i] = phoneList[i+1];
		}
        cnt--;
        System.out.println(" > 정보를 성공적으로 삭제했습니다.");
	}
}
  • Main에서 case 4에 해당하는 메소드
  • 삭제할 이름을 입력받고, idx 값이 -1이 아닐 경우 삭제할 이름이 있는 인덱스의 뒤부터 한 칸씩 앞으로 앞당겨서 값을 덮어쓴다.

 


 

질문한 내용이나 어려웠던 점 메모

1. 수정 (질문할 예정)

  • 수정할 이름을 입력받고 클래스에 따라 수정을 다르게 하고 싶었는데 아직 수정 코드를 작성하라고 하지 않으신 상태여서 나중에 다시 여쭤보기로 했다.

2. 삭제

  • for문을 한 번만 쓰면서 삭제할 자리의 뒤부터 한 칸씩 앞으로 앞당기기를 해보려고 했는데 for문을 한 번만 사용하니 자꾸 null값이 뜨고 그래서 결국 성공하지 못했다..

 


728x90
728x90

 

수업내용 정리 (Java)

 

1. 상속

  • 상속은 오버라이딩을 통해 다형성을 활용하기 위해서 사용한다.
  • 부모(상위) 클래스와 자식(하위) 클래스로 나눈다.
  • 자식 클래스가 부모 클래스를 상속. 이때, 정보은닉이 우선적이라 상속을 해도 직접 부모 클래스의 private 필드를 언급할 수 없다.
  • 부모타입 참조변수는 자식 인스턴스를 참조할 수 있다. 반대의 경우, 불가능!
  • Person p(참조변수) = new Student("kim", 20, 1);(자료형 변수)
  • IS-A 관계(Person⬅️Student ⬅️PartTimeStudent / ex: Student is a Person)

 

 1-1) Ex01 ㄱ 

더보기

메인 클래스

Person p = new Person("cha", 20);
  • Person class 객체

 

Student s1 = new Student("kim",30,1);
s1.eat();
s1.sleep();
s1.study();
s1.exam();
s1.showInfo();
System.out.println(s1);
  • Student class 객체

 

Student pts = new PartTimeStudent("choi", 22, 5, 9620, 20);
// Student 눈에는 Student의 멤버만 보인다.
pts.showInfo();
pts.sleep();
pts.eat();
pts.study();
pts.exam();
//pts.work();
  • Student 타입의 PartTimeStudent class 객체
  • Student class를 참조변수로 PartTimeStudent class를 자료형 변수로 사용한 경우.
  • Student class나 Student의 상위 클래스의 메소드만 사용할 수 있다. (오버라이딩 가능/PartTimeStudent class 메소드 사용 불가능)
  • PartTimeStudent class에는 work 메소드가 있지만 Student class에 work 메소드가 없기 때문에 사용 시 에러가 난다.

 

fct(new Person("사람",10));
fct(new Student("학생",20,1));
fct(new PartTimeStudent("근로학생",30,2,9000,10));
  • fct 메소드 사용

 

private static void fct(Person person) {
person.showInfo();
System.out.println("-----------");
}
  • 다형성
  • fct 메소드에 매개변수로 Person 객체를 생성한다.
  • 자식(하위) 객체를 생성할 때, 변수 타입을 부모(상위) 클래스로 사용할 수 있다.
  • 단, 부모(상위) 객체를 생성할 때, 자식(하위) 클래스를 타입으로 사용할 수는 없다.

 

 1-2) Person ㄱ 

더보기

부모(조상, 상위) 클래스

// 필드(특성)
private String name;
private int age;
  • 자식 클래스가 공유하는 필드

 

// 생성자
public Person() {
	System.out.println("Person() call");
	this.name = "noName";
	this.age = 1;
}
public Person(String name, int age) {
	this.name = name;
	this.age = age;
}
  • 기본 생성자로 객체를 생성하면 자동으로 name은 noName, age는 1로 값이 들어간다.
  • 자식 클래스에서 생성할 때, 호출하여 사용할 수 있다.

 

// 메소드(행위)
public void sleep() {
	System.out.println("사람은 8시간 잔다.");
}
public void eat() {
	System.out.println("사람은 세끼를 먹는다.");
}
public void showInfo() {
	System.out.println("name: "+name);
	System.out.println("age : "+age);
}
  • 해당 메소드를 자식 클래스에서 호출하여 사용할 수 있다.

 

@Override
public String toString() {
	String str = ("name: "+name+"\nage : "+age);
	return str;
}
  • 기본적으로 toString 메소드가 숨겨진 상태로 존재하는데 불러서 고쳐서 사용하는 것을 오버라이딩이라고 한다.

 

 1-3) Student ㄱ 

더보기

자식(후손, 하위) 클래스

// 필드
// name, age, sleep(), eat()
private int sNo;
  • 두번째 줄의 주석처리 부분은 부모 클래스에서 상속한 필드 및 메소드

 

// 생성자
public Student(String name, int age, int sNo) {
	super(name,age);	// 부모 클래스 호출
	this.sNo = sNo;
}
  • super(); 은 부모 클래스를 호출하는 코드.
  • 자식 생성자를 먼저 호출하고 자식 생성자에서 부모 생성자를 호출하지만 실행되는 순서는 부모>자식 순으로 한다.
    1. 자식생성자 호출
    2. 부모생성자 호출>실행
    3. 자식생성자 실행
    4. 자식 객체 생성
  • ex) super(); == Person(); / super(name, age); == Person(name, age);
  • super로 부모 클래스를 호출했기 때문에 this.sNo만 저장하면 된다.

 

// 메소드
public void study() {
	System.out.println("학생은 공부를 한다.");
}
public void exam() {
	System.out.println("학생은 시험을 본다.");
}

 

/* 빈 칸에 두고 ctrl+spece bar 누르면 Override(재정의) 할 메소드가 뜸! */

 

// 메소드 재정의(오버라이딩)
@Override
public void sleep() {
	super.sleep();	//Person의 sleep();
	System.out.println("GAME, TV를 줄인다.");
}
@Override
public void eat() {
	System.out.println("학생은 두끼를 먹는다.");
}
@Override
public void showInfo() {
	super.showInfo();	// Person.showInfo();
	System.out.println("sNo : "+sNo);
}
@Override
public String toString() {
	String str = "\nsNo : "+sNo;
	return super.toString()+str;
	/* super.toString(); == 부모의 toString을 호출
	 * toString(); == 본인의 toString을 호출
	 * toString에서 return toString을 하면 에러가 남 */
}
  • 메소드 위에 @Override가 있으면 메소드에 오류가 있을때 걸러준다.
  • 부모 클래스에 있는 메소드를 해당 클래스에 맞춰 재정의하는 것이 오버라이딩이다.
  • toString에서 return toString을 하면 본인의 메소드를 계속 재실행하기 때문에 에러가 난다.

 

 1-4) PartTimeStudent ㄱ 

더보기

자식(후손, 하위)의 자식 클래스

// 필드
private int pay;
private int workTime;

 

// 생성자
public PartTimeStudent(String name, int age, int sNo, int pay, int workTime) {
	super(name, age, sNo);
	this.pay = pay;
	this.workTime = workTime;
}
  • super();을 통해 부모 생성자를 호출하여 저장하고, 본인 필드에 값을 저장한다.

 

// 메소드
public void work() {
	System.out.println("근로학생은 일을 한다.");
	workTime++;
}

 

// 오버라이딩(메소드 재정의)
@Override
public void showInfo() {
	super.showInfo();	// Student.showInfo();
	System.out.println("주급 : "+(pay*workTime));
}
@Override
public void sleep() {
	System.out.println("근로학생은 4시간 잔다.");
}
@Override
public String toString() {
	String str = "\n주급 : "+(pay*workTime);
	return super.toString()+str;
}
  • 맨 위의 메소드는 부모메소드를 호출하고, 추가적으로 출력할 내용을 추가했다.

 


 

질문한 내용이나 어려웠던 점 메모

1. 상속

  • 부모타입 참조변수는 자식 인스턴스를 참조할 수 있다.
  • ⬆️를 이해하지 못해서 일단 외우기로 했다.

 


 

전체 피드백

  • 이해하진 못하더라도 응용할 수 있게 외우기

 


728x90
1 ··· 5 6 7 8 9 10 11 ··· 13