java

14일차 2023-03-27

choi Hoon 2023. 3. 27. 19:07

1. 추상클래스 

상속이 목적이다.

class 앞에 abstract를 붙이면 추상클래스가 된다.

동일 API를 사용할 수 있다.

인스턴스화가 불가능 그래서 메모리가 할당하지 않음

 

2. 추상 메소드 

추상메소드는 오버라이딩이 목적

메소드 앞에 abstract를 붙은 것

구현부{}가 없음

abstract메소드이면 그 메소드를 가진 클래스는 추상클래스여야 한다.

추상 클래스지만 추상 메소드가 없는 걸 상속받은 경우 꼭 오버라이딩 할 필요 없다.

AbstractBasic.java

package abstract17;
/*
[추상클래스-불완전한 설계도]
1]class 앞에 abstract(modifier)를 붙이면 
  그 클래스는 추상 클래스가 된다
2]어떤 클래스가 추상 메소드를 가지면 
  그 클래스를 반드시
  추상 클래스로 만들어 줘야 한다 
  단, 추상 메소드가 없어도 abstract만 붙이면 
  추상 클래스가 될 수 있다.
  
  ※추상 메소드란?
    - 메소드 앞에 abstract키워드가 붙은 것
    - 메소드 원형만 있고 구현부가 없는것
      예] 접근지정자 abstract 반환타입 메소드명([매개변수]);
    - 추상메소드는 오버라이딩이 목적이다
 
3]추상 클래스는 인스턴스화 할 수 없다.즉 메모리에 객체를
  생성할 수 없다 즉 new연산자로 메모리를 할당 할 수 없다.   
  
4]추상클래스는 상속이 목적이다
5]추상 클래스를 상속받은 자식클래스(sub class)에서는
   만약 추상 클래스가(super class) 하나라도 추상 메소드를
   가지고 있다면 반드시 오버라이딩 해야 한다
   즉 동일한 API를 사용할 수 있다.
   
   
6]만약 자식클래스에서 부모클래스의 추상메소드를 오버라이딩 하지
  않으려면 자식도 추상 클래스로 만들어야 한다
   
7] 추상클래스는 new해서 인스턴스화 할 수 없지만
     추상클래스 타입의 인스턴스 변수에 
     자식클래스의 메모리를 할당 할 수 있다(Heterogenious)
   
*/
//추상 클래스1]-추상 메소드가 없는 추상 클래스
abstract class NoHavingAbstractMethod{
	//[멤버상수]
	public static final int MAX_INT = Integer.MAX_VALUE;
	//[멤버변수]
	int instanceVar;
	static int staticVar;
	//[멤버 메소드]
	void instanceMethod() {}
	static void staticMethod() {}
}//////////////
//추상클래스2]- 추상 메소드를 가진 클래스
abstract class HavingAbstractMethod{
	//void abstractMethod();[x]추상 메소드가 아니다.구현부가 없어서 에러
	/*
	  추상 메소드를 멤버로 가지면 그 클래스는 
	  반드시 추상 클래스가 되야 한다.
	 */
	abstract void abstractMethod();//[o]
}//////////////////////

class NoHavingChild extends NoHavingAbstractMethod{
	
	int newVar;
	/*추상 메소드를 가지지 않은 추상 클래스를 
	  상속받은 경우
	  강제적으로 오버라이딩 할 의무는 없다.
	  정적 메소드는 오버라이딩 불가
	 */
	//[강제사항 아님-임의로 오버라이딩 한것임]
	@Override
	void instanceMethod() {}
	
}

class HavingChild extends HavingAbstractMethod{

	//[의무적으로 오버라이딩한 메소드]
	@Override
	void abstractMethod() {}
	//자식에서 새롭게 추가한 메소드
	void newMethod() {}
}
/*
추상클래스3]
추상메소드를 가진 추상 클래스를 상속받은
자식클래스에서 의무적으로 오버라이딩 안하려면
자식클래스도 추상 클래스로 만들어 주면 된다.
*/
abstract class HavingChildNoOverriding extends HavingAbstractMethod{
	abstract void abstractNewMethod();
}/////////////

class HavingNewChild extends HavingChildNoOverriding{

	@Override
	void abstractNewMethod() {}
	@Override
	void abstractMethod() {}
	
}///////////////////////////////


public class AbstractBasic {

	public static void main(String[] args) {
		//1.추상 클래스는 인스턴스화 불가]-자식타입으로는 객체생성 가능
		//NoHavingAbstractMethod name= new NoHavingAbstractMethod();//[x]
		NoHavingAbstractMethod name=new NoHavingChild();//[o]이질화
		//2.추상클래스 타입의 인스턴스 변수에 자식클래스 타입의 메모리 할당-이질화]
		HavingAbstractMethod ham = new HavingChild();
		ham.abstractMethod();
		((HavingChild)ham).newMethod();
		//추상클래스의 정적멤버:(자식 혹은 부모)클래스명.정적멤버
		NoHavingAbstractMethod.staticMethod();
		NoHavingChild.staticMethod();
	}///////////////main

}//////////////////class

1-1) Figure.java

package abstract17;

public abstract class Figure {
	//[멤버변수]
	int width,height,radius;
	//[기본 생성자]
	public Figure() {
		System.out.println("Figure(추상 클래스)의 기본 생성자");
	}////////////
	//[인자 생성자]
	public Figure(int radius) {				
		this.radius = radius;
		System.out.println("Figure(추상 클래스)의 인자 생성자-radius");
	}///////////////////////////
	public Figure(int width, int height) {		
		this.width = width;
		this.height = height;
		System.out.println("Figure(추상 클래스)의 인자 생성자-width,height");
	}
	//[추상 메소드]
	//도형의 면적을 구하는 추상 메소드
	abstract void area(String figureName);
}

Circle.java

package abstract17;

public class Circle extends Figure {

	
	public Circle(int radius) {
		super(radius);
		System.out.println("Circle의 인자 생성자");
	}

	@Override
	void area(String figureName) {
		System.out.println(figureName+"의 면적:"+(int)(radius*radius*Math.PI));		
	}

}

Rectangle.java

package abstract17;

public class Rectangle extends Figure {

	
	public Rectangle(int width, int height) {
		super(width, height);
		System.out.println("Rectangle의 인자 생성자");
	}

	@Override
	void area(String figureName) {
		System.out.println(figureName+"의 면적:"+width*height);		
	}

}

Truangle.java

package abstract17;

public class Triangle extends Figure {

	
	public Triangle(int width, int height) {
		super(width, height);
		System.out.println("Triangle의 인자 생성자");
	}
	@Override
	void area(String figureName) {
		System.out.println(figureName+"의 면적:"+(int)(width*height*0.5));		
	}

}

FigureApp.java

package abstract17;

public class FigureApp {

	public static void main(String[] args) {
		//Figure f = new Figure();//[x]인스턴스화 불가
		Figure f = new Rectangle(100, 100);
		f.area("사각형");
		f= new Triangle(100, 100);
		f.area("삼각형");
		f= new Circle(100);
		f.area("원");
	}/////////////////main
}////////////////////class

console로 만드는 crud메인 메뉴 (아직 미완성)

create, read, udatele, delete

Person.java

package console.academy;

public class Person {
	//[멤버변수]
	String name;
	int age;
	//[기본 생성자]
	Person() {}
	//[인자 생성자]
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	//[맴버 메소드]
	String get() {//왜 이렇게 두 번쓰는가 그냥 print에 넣어도 되는데=>GuI에서 여기를 호출하기 위해
		return String.format("이름:%s,나이:%s", name,age);
	}
	void print() {
		System.out.println(get());
	}
}

Person을 상속받은 Student.java

package console.academy;

public class Student extends Person {
	//[멤버변수]
	public String stNumber;//새롭게 확장한 멤버
	//[인자 생성자]
	public Student(String name, int age,String stNumber) {
		super(name, age);
		this.stNumber = stNumber;
	}////////////////////
	//[멤버 메소드]
	@Override
	String get() {		
		return String.format("%s,학번:%s",super.get(),stNumber);
	}//////////
	@Override
	void print() {
		System.out.println(get());
	}/////////
	
}///////////////

Person을 상속받은 Teacher.java

package console.academy;

public class Teacher extends Person {
	//[멤버변수]
	String subject;//새롭게 확장한 멤버
	//[인자 생성자]
	public Teacher(String name, int age,String subject) {
		super(name, age);
		this.subject= subject;
	}////////////////
	@Override
	String get() {		
		return String.format("%s,과목:%s", super.get(),subject);
	}/////////////
	@Override
	void print() {
		System.out.println(get());		
	}////////////////
}

 AcademyLogic.java

package console.academy;

import java.util.Scanner;

public class AcademyLogic {
	//[멤버 상수]
	public static final int MAX_PERSON = 3;//최대 인원수
	//[멤버변수]
	Person[] person;
	//[생성자]
	public AcademyLogic() {
		person = new Person[MAX_PERSON];
	}//////////////////////
	//[멤버 메소드]
	/*
	 * 1]메뉴 출력용 메소드
	 * 매개변수:NO
	 * 반환타입:void
	 */
	public void printMainMenu() {
		System.out.println("====================메인 메뉴====================");
		System.out.println(" 1.입력 2.출력 3.수정 4.삭제 5.검색 6.파일저장 9.종료");
		System.out.println("===============================================");
		System.out.println("메인 메뉴번호를 입력하세요?");
	}//////////////printMainMenu()
	/*
	 * 2]메뉴 번호 입력용 메소드
	 * 매개변수:NO
	 * 반환타입:int
	 */
	public int getMenuNumber() {
		Scanner sc = new Scanner(System.in);
		String menuStr = sc.nextLine().trim();
		return Integer.parseInt(menuStr);
	}///////////////getMenuNumber()
	/*
	 * 3]메뉴 번호에 따른 분기용 메소드
	 * 매개변수:int(메인메뉴)
	 * 반환타입:void
	 */
	public void seperateMainMenu(int mainMenu) {
		switch(mainMenu) {
			case 1://입력
				while(true) {
					//서브메뉴 출력]
					printSubMenu();
					//서브메뉴번호 입력받기]
					int subMenu = getMenuNumber();
					if(subMenu == 3) break;
					switch(subMenu) {
						case 1:
						case 2:setPerson(subMenu);break;
						default:System.out.println("서브메뉴에 없는 번호입니다");
					}
				}///while
				break;
			case 2://출력
				printPerson();
				break;
			case 3://수정
				updatePerson();
				break;
			case 4://삭제
				deletePerson();
				break;
			case 5://검색
				searchPerson();
				break;
			case 6://파일저장
				break;
			case 9://종료
				System.out.println("프로그램을 종료 합니다");
				System.exit(0);
			default:System.out.println("메뉴에 없는 번호입니다");
		}///switch
		
	}///////////////////seperateMainMenu(int mainMenu)	
	
	/*
	 * 4]서브메뉴 출력용 메소드
	 * 매개변수:NO
	 * 반환타입:void
	 */
	private void printSubMenu() {
		System.out.println("++++++++++서브 메뉴++++++++++");
		System.out.println("1.학생 2.교사 3.메인메뉴로 이동");
		System.out.println("+++++++++++++++++++++++++++");
		System.out.println("서브 메뉴번호를 입력하세요?");
	}///////////////printSubMenu()
	/*
	 * 5]서브메뉴에 따른 학생 및 교사 데이타 입력용 메소드
	 * 매개변수:int(서브메뉴)
	 * 반환타입:void
	 */
	private void setPerson(int subMenu) {
		//정원이 찼는지 여부 판단]
		int index = -1;//채워지지 않은 Person형 배열(null인 배열요소)의 인덱스를 저장할 변수
		for(int i=0;i < MAX_PERSON;i++) {
			if(person[i]==null) {
				index = i;
				break;
			}
		}
		if(index == -1) {//이미 정원이 찬 경우
			System.out.println("정원이 찼어요..더 이상 입력할 수 없어요");
			return;
		}
		//정원이 안 찬 경우 즉 index가 -1이 아닌 경우...
		Scanner sc = new Scanner(System.in);
		System.out.println("이름을 입력하세요?");
		String name = sc.nextLine().trim();
		System.out.println("나이를 입력하세요?");
		int age = Integer.parseInt(sc.nextLine().trim());
		//학생과 교사를 구분해서 입력받기]
		switch (subMenu) {
			case 1://학생인 경우
				System.out.println("학번을 입력하세요?");
				String stNumber = sc.nextLine().trim();
				person[index]=new Student(name, age, stNumber);
				break;
			default:
				System.out.println("과목을 입력하세요?");
				String subject = sc.nextLine().trim();
				person[index]= new Teacher(name, age, subject);
		}
	}/////////////////setPerson(int subMenu) 
	/*
	 * 6]출력용 메소드
	 * 매개변수:NO
	 * 반환타입:void
	 */
	private void printPerson() {
		System.out.println("[학생/교사 구분없이 출력]");
		for(int i=0;i < MAX_PERSON;i++) {
			if(person[i] !=null) person[i].print();
		}
		//문] 학생과 교사를 구분해서 출력하여라
		/*
		    [학생 목록]
		    이름:가학생,나이:28,학번:2014
		    이름:나학생,나이:28,학번:2015
		    [교사 목록]
		    이름:가교사,나이:30,과목:자바		
		 */
		System.out.println("[학생/교사 구분해서 출력]");
		//학생 답안
		/*
		System.out.println("[학생 목록]");
		for(int i=0;i<MAX_PERSON;i++) {
			if(person[i]!=null && person[i] instanceof Student) {
				person[i].print();
			}
		}
		System.out.println("[교사 목록]");
		for(int i=0;i<MAX_PERSON;i++) {
			if(person[i]!=null && person[i] instanceof Teacher) {
				person[i].print();
			}
		}*/
		StringBuffer student = new StringBuffer("[학생 목록]\r\n");
		StringBuffer teacher = new StringBuffer("[교사 목록]\r\n");
		for(int i=0; i < MAX_PERSON;i++)
			if(person[i] !=null)
				if(person[i] instanceof Student)
					student.append(person[i].get()+"\r\n");
				else
					teacher.append(person[i].get()+"\r\n");
		
		System.out.println(student.toString()+teacher);
	}//////////////printPerson()
	/*
	 * 7]이름으로 검색하는 메소드
	 * 매개변수:String(수정/삭제/검색용 타이틀)
	 * 반환타입:Person타입
	 */
	private Person findPersonByName(String title) {
		System.out.println(title+"할 사람의 이름을 입력하세요?");
		Scanner sc = new Scanner(System.in);
		String name= sc.nextLine().trim();
		for(int i=0; i < MAX_PERSON;i++)
			if(person[i] !=null)
				if(person[i].name.equals(name))
					return person[i];
		System.out.println(name+"로(으로) 검색된 정보가 없어요");
		return null;
	}/////////////////findPersonByName(String title) 
	//8]검색용 메소드
	private void searchPerson() {
		Person findPerson=findPersonByName("검색");
		if(findPerson !=null) {
			System.out.printf("[%s로 검색한 결과]%n",findPerson.name);
			findPerson.print();
		}
	}//////////searchPerson()
	//9]수정용 메소드
	private void updatePerson() {
		Person findPerson=findPersonByName("수정");
		if(findPerson !=null) {
			Scanner sc = new Scanner(System.in);
			//나이 수정
			System.out.printf("(현재 %s살) 몇 살로 수정할래?%n",findPerson.age);
			findPerson.age = Integer.parseInt(sc.nextLine().trim());
			//학생인지 교사인지 판단
			if(findPerson instanceof Student) {//학생
				System.out.printf("(현재 %s) 몇 학번으로 수정할래?%n",((Student)findPerson).stNumber);
				((Student)findPerson).stNumber = sc.nextLine().trim();
			}
			else {
				System.out.printf("(현재 %s) 무슨 과목으로 수정할래?%n",((Teacher)findPerson).subject);
				((Teacher)findPerson).subject = sc.nextLine().trim();
			}
			System.out.printf("[%s(이)가 아래와 같이 수정되었습니다]%n",findPerson.name);
			findPerson.print();//수정내용을 확인하기 위한 출력
			
		}//////////////
	}///////////updatePerson()
	//10]삭제용
	//문]삭제처리 하시오(힌트:찾은 Person형 배열 요소를 null로 설정) 
	private void deletePerson() {
		Person findPerson=findPersonByName("삭제");
		if(findPerson !=null) {
			for(int i=0; i < MAX_PERSON;i++)
				if(findPerson.equals(person[i])) {
					person[i]=null;
					System.out.printf("[%s가 삭제 되었습니다]%n",findPerson.name);
					break;
				}
		}
	}//////////////
}/////////////class

AcademyApp.java

package console.academy;

public class AcademyApp {

	public static void main(String[] args) {
		//[배열 사용]
		AcademyLogic logic=new AcademyLogic();
		while(true) {
			//1.메인 메뉴 출력
			logic.printMainMenu();
			//2.메인메뉴 번호 입력받기
			int mainMenu=logic.getMenuNumber();
			//3. 메인 메뉴에 따른 분기
			logic.seperateMainMenu(mainMenu);
		}
	}
}