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);
}
}
}