● Human 클래스
// 추상 클래스
abstract class Human {
private char type; // 성별
private String name;
private int age;
public Human() {
this.type = 0;
this.name = "";
this.age = 0;
}
public Human(char type, String name, int age) {
this.type = type;
this.name = name;
this.age = age;
}
// 추상 메소드 모든 자식은 일단 무조건 구현해야한다.
public abstract void print();
// getter
public char getType() {
return type;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
// setter
public void setType(char type) {
this.type = type;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
● Student 클래스
import java.util.Arrays;
public class Student extends Human {
final static String JOB = "학생";
// 멤버 변수
private String className;
private int[] score;
// 생성자
public Student() {
super();
className = "";
score = new int[5];
}
public Student(String className, char type, String name, int age, int[] score) {
super(type, name, age);
this.className = className;
this.score = score;
}
// setter
public void setClassName(String className) {
this.className = className;
}
public void setScore(int index, int score) {
this.score[index] = score;
}
// getter
public String getClassName() {
return this.className;
}
public int getScore(int index) {
return this.score[index];
}
@Override
public void print() {
System.out.println("============ 나의 학생 정보 =============");
System.out.println(className + "입니다.");
System.out.println("이름은 " + this.getName() + "입니다.");
System.out.println("나이는 " + this.getAge() + "입니다.");
// Arrays.toString을 이용하여 배열의 값을 문자열로 표시
System.out.println("점수는 " + Arrays.toString(score) + "점 입니다.");
System.out.println("총점은 " + this.getTotal() + "점입니다.");
System.out.println("평점은 " + this.getAverage() + "점입니다.");
System.out.println("=====================================");
}
// 총점 계산하기 메소드
public int getTotal() {
int total = 0;
for (int i = 0; i < score.length; i++) {
total += score[i];
}
return total;
}
// 평균 계산하기 메소드
public double getAverage() {
return getTotal() / this.score.length;
}
// Object 클래스의 equals() 메소드 오버라이딩(재정의)
@Override
public boolean equals(Object obj) {
// 이와 같이 해도 문제는 없지만 오류에 취약한다.
// return this.value == ((ObjectTest)obj).value;
// 그래서 예상 가능한 오류를 처리한다.
if(obj instanceof Student) {
Student st = (Student)obj;
boolean a = st.getType() == this.getType();
boolean b = st.getAge() == this.getAge();
boolean c = st.getClassName().equals(this.className);
boolean d = st.getName().equals(this.getName());
boolean e = Arrays.equals(st.score, this.score);
if( a && b && c && d && e) {
return true;
} else {
return false;
}
} else {
return false;
}
// 좀더 간력하게하는 방법.
// if(obj instanceof Student) {
// Student st = (Student)obj;
//
// boolean a = st.getType() == this.getType();
// boolean b = st.getAge() == this.getAge();
// boolean c = st.getClassName().equals(this.className);
// boolean d = st.getName().equals(this.getName());
// boolean e = Arrays.equals(st.score, this.score);
//
// if( a && b && c && d && e) return true;
// }
//
// return false;
}
// Object 클래스의 toString() 메소드 오버라이딩(재정의)
@Override
public String toString() {
return this.className + " " + this.getName() + " " + this.getAge();
// return super.toString();
}
● Teacher 클래스
public class Teacher extends Human {
final static String JOB = "선생님";
// 멤버 변수
private String className;
// 생성자
public Teacher() {
super();
this.className = "";
}
public Teacher(String className, char type, String name, int age) {
super(type, name, age);
this.className = className;
}
// setter
public void setClassName(String className) {
this.className = className;
}
// getter
public String getClassName() {
return className;
}
// print 메소드(추상 메소드 오버라이드)
@Override
public void print() {
System.out.println("============ 나의 선생님 정보 =============");
System.out.println(className + "입니다.");
System.out.println("이름은 " + this.getName() + "입니다.");
System.out.println("나이는 " + this.getAge() + "입니다.");
System.out.println("성별은 " + this.getType() + "입니다.");
System.out.println("=====================================");
}
}
● ClassRoom
import java.util.ArrayList;
import java.util.Iterator;
public class ClassRoom {
private String className;
private Teacher teacher;
private ArrayList<Student> students;
ClassRoom() {
className = "";
teacher = new Teacher();
// 생성만하고 초기화는 필요없다
students = new ArrayList<>();
}
ClassRoom(String className) {
this(); // 초기화를 꼭 해줘야 한다.
this.setClassName(className);
}
public void setClassName(String className) {
// 내 클래스의 멤버 변수에 먼저 저장하고
this.className = className;
// 선생님과 학생들도 변경해주자.
this.teacher.setClassName(className);
// 컬렉션은 Iterator을 이용해서 반복해야한다.
for (Iterator<Student> iter = students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
student.setClassName(className);
}
}
// 컬렉션의 set 메소드를 이용해야한다.
public void setStudent(int index, Student student) {
// 오류 발생 outOfBounds error를 방어하기위한 방어 코드
int length = students.size();
if(index > length-1) {
System.err.printf("index(%d) 가 List length(%d) 보다 크므로 설정할수 없습니다.\n", index, length);
return;
}
students.set(index, student);
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public String getClassName() {
return this.className;
}
// 컬렉션의 get 메소드를 이용해아한다.
public Student getStudent(int index) {
return students.get(index);
}
public Teacher getTeacher() {
return teacher;
}
public void printClassName() {
System.out.println(className + "입니다.");
}
public void printTeacher() {
this.teacher.print();
}
public void printStudents() {
// 컬렉션은 Iterator을 이용해서 반복해야한다.
for (Iterator<Student> iter = students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
// print 메서드를 깔끔하게 한번 정리하고 가자
student.print();
}
}
// 컬렉션의 set 메소드를 이용해야한다.
public void setStudent(int index, char type, String name, int age, int[] score) {
/*
* 클래스 외부에서 메소드를 통해 입력한 각각의 정보를 이용해
* 내부에서 클래스 객체를 만들어 이 객체를
* 멤버 객체 변수인 teacher에 저장한다.
*/
students.set(index, new Student(this.className, type, name, age, score));
}
public void setTeacher(char type, String name, int age) {
/*
* 클래스 외부에서 메소드를 통해 입력한 각각의 정보를 이용해
* 내부에서 클래스 객체를 만들어 이 객체를
* 멤버 객체 변수인 teacher에 저장한다.
*/
this.teacher = new Teacher(this.className, type, name, age);
}
// 컬렉션 size 메소드를 이용
public int getStudentCount() {
return students.size();
}
public int getTotal() {
int total = 0;
// for (Iterator<Student> iter = students.iterator(); iter.hasNext();)
// 문을 보다 편리하게 사용할수 있는 for(일반적으로 foreach라 부른다) 문
for (Student student : students) {
total += student.getTotal();
}
return total;
}
// 컬렉션 size 메소드를 이용
public double getAverage() {
// List 배열의 크기가 0보다 작으면 / by zero 오류가 발생
if(students.size() <= 0) return 0;
return this.getTotal() / students.size() / 5.0;
}
// 학생을 list 컬렉션의 마자막에 추가하는 메소드 추가
// 추가하고 난후 사이즈를 반환하자.
public int addStudent(Student student) {
students.add(student);
return students.size();
}
public ArrayList<Student> getStudents() {
return this.students;
}
// ClassRoom의 정보(학과, 선생님, 학생 정보 등)를 화면에 출력하는 메소드
public void print() {
Teacher tc = this.getTeacher();
System.out.println("==========================================================");
System.out.printf("%s 선생님 : %s(%d) 학생: %d명",
className, tc.getName(), tc.getAge(), this.getStudentCount());
System.out.printf("\t총점: %d 평균: %.1f", this.getTotal(), this.getAverage());
System.out.println();
System.out.println();
System.out.println("----------------------------------------------------------");
System.out.printf("번호 이름 나이 국어 영어 수학 사회 과학 총점 평균\n");
System.out.println("----------------------------------------------------------");
// for (Iterator<Student> iter = students.iterator(); iter.hasNext();)
// 문을 보다 편리하게 사용할수 있는 for(일반적으로 foreach라 부른다) 문
int no = 1;
for (Student item : students) {
System.out.printf("%2d ", no++);
System.out.printf("%5s ", item.getName());
System.out.printf("%4d ", item.getAge());
for (int i = 0; i < 5; i++) {
System.out.printf("%4d ", item.getScore(i));
}
System.out.printf("%4d\t", item.getTotal());
System.out.printf("%5.1f", item.getAverage());
System.out.println();
}
System.out.println("==========================================================");
}
}
● SpecialJob 인스턴스
public interface SpecialJob {
public abstract int getJobLevel();
public abstract String getJobName();
public abstract void setJobLevel(int level);
public abstract void setJobName(String jobname);
}
● Boss 클래스
public class Boss extends Teacher implements SpecialJob {
final static String JOB = "교장선생님";
final static String SCHOOL = "코리아IT학교";
private int joblevel;
private String jobname;
private int roomno;
public Boss() {
this('남', "", 0);
joblevel = 10;
roomno = 101;
}
public Boss(char type, String name, int age) {
// 교장선생님은 맡은 반이 없다.
// 그래서 className을 학교이름으로 설정
super(SCHOOL, type, name, age);
jobname = JOB;
joblevel = 10;
roomno = 101;
}
@Override
public int getJobLevel() {
return joblevel;
}
@Override
public String getJobName() {
return jobname;
}
public int getRoomNo() {
return roomno;
}
public String getSchool() {
return this.getClassName();
}
@Override
public void setJobLevel(int joblevel) {
this.joblevel = joblevel;
}
@Override
public void setJobName(String jobname) {
this.jobname = jobname;
}
public void setRoomNo(int roomno) {
this.roomno = roomno;
}
public void setSchool(String school) {
this.setClassName(school);
}
@Override
public void print() {
System.out.println("============ 나의 직업 정보 =============");
System.out.println( this.getClassName() + "의 " + jobname + "입니다.");
System.out.println("이름은 " + this.getName() + "입니다.");
System.out.println("나이는 " + this.getAge() + "입니다.");
System.out.println("방번호는 " + roomno + "호 입니다.");
System.out.println("직급으로는 " + joblevel + "레벨 입니다.");
System.out.println("=====================================");
}
}
● ScanRoom 클래스
import java.util.Scanner;
public class ScanRoom {
// Scanner 클래스 객체를 하나 선언한다.
private Scanner sc;
private String className = ""; // 학과명 저장을 위해 선언
// 생성자
public ScanRoom() {
// Scanner 객체를 초기화(생성)한다.
sc = new Scanner(System.in);
className = "";
}
// ScanRoom 클래스의 사용법을 표시하는 메소드
public void printGuide() {
System.out.println("1. 학과명을 입력합니다.");
System.out.println("2. 선생님 정보를 입력합니다.");
System.out.println("3. 학생 정보를 입력합니다.");
System.out.println("4. 모든 입력은 한줄에 띄어쓰기로 구분해서 입력하세요.");
System.out.println("5. 입력예는 아래와 같습니다.");
System.out.println("====================================================");
System.out.println("학과 이름을 입력 : 컴퓨터공학과");
System.out.println("선생님 정보 입력(성별 이름 나이) : 남 홍길동 50");
System.out.println("학생 정보 입력(성별 이름 나이) (1) : 남 김유신 23");
System.out.println("학생 정보 입력(성별 이름 나이) (2) : 남 이순신 21");
System.out.println("학생 정보 입력(성별 이름 나이) (3) : 여 유관순 20");
System.out.println("......");
System.out.println("학생 정보 입력(성별 이름 나이) (10) : 여 김영희 18");
System.out.println("====================================================");
System.out.println();
}
// 사용자로부터 학과명을 입력받기 위한 메소드
public String scanClassName() {
System.out.print("학과 이름을 입력 : ");
className = sc.next();
return className;
}
// 사용자로부터 선생님 정보를 입력받기 위한 메소드
// 사용예 : 선생님 정보 입력(성별 이름 나이) : 남 홍길동 50
public Teacher scanTeacher() {
System.out.print("선생님 정보 입력 : ");
char type = sc.next().charAt(0);
String name = sc.next();
// int age = sc.nextInt();
// Wrapper 클래스를 이용해 형변환하여 받는 방법
int age = Integer.valueOf(sc.next());
Teacher object = new Teacher(className, type, name, age);
return object;
}
// 사용자로부터 사용자 정보를 입력받기 위한 메소드
// 사용예 : 학생 정보 입력(성별 이름 나이) (1) : 남 김유신 23
public Student scanStudent(int no) {
System.out.printf("학생 정보 입력(성별 이름 나이) (%d) : ", no);
char type = sc.next().charAt(0);
String name = sc.next();
int age = sc.nextInt();
int score[] = new int[5];
// 학생들의 점수는 random 메소드를 이용해 0~100점까지의 점수를 생성합니다.
// 5번 랜덤을 * 100을 한 이유는 random은 0.0 ~ 0.1까지의
// 소수를 반환하므로 *100을하여 0 ~ 100까지의 숫자를 만들기 위함
int random = (int)(Math.random() * 100);
score[0] = random;
score[1] = random;
score[2] = random;
score[3] = random;
score[4] = random;
//for 문이용하기
// for (int i = 0; i < score.length; i++) {
// score[i] = random;
// }
Student object = new Student(className, type, name, age, score);
return object;
}
// 학과명을 자동 테스트하기 위한 메소드
public String makeClassName() {
className = "컴퓨터공학과";
return className;
}
// 선생님 정보를 자동 테스트하기 위한 메소드
public Teacher makeTeacher() {
return new Teacher(this.className, '남', "홍길동", 30);
}
// 학생정보를 자동 테스트하기 위한 메소드
public Student makeStudent() {
// 점수는 그냥 random으로 받자.
int random = (int)(Math.random() * 100);
int score[] = new int[]{random, random, random, random, random};
// random 값이 짝수면 '여' 홀수면 '남'으로 설정하자.
char type = random % 2 == 0 ? '여' : '남';
// 타입이 '여'이면 이름을 영희로 '남'이면 철수로 설정하자.
String name = type == '여' ? "김영희" : "박철수";
return new Student(this.className, type, name, 30, score);
}
}
● 메인
public class Aschool {
public static void main(String[] args) {
// Console에서 사용자로부터 입력 받아 처리하는 테스트
// testCreateClassRoom(1);
// 자동으로 코드를 통해 예제를 만들어 처리하는 테스트
testMakeClassRoom(10);
}
static public void testCreateClassRoom(int count) {
// 입력 테스트를 위한 유틸리티 클래스 객체를 생성하자.
ScanRoom scan = new ScanRoom();
// 사용자 입력을 위한 가이드를 출력하자.
scan.printGuide();
// 학과명를 console 화면을 통해 입력받는 메소드
String clsname = scan.scanClassName();
// 입력받은 학과명을 ClassRoom에 저장
ClassRoom room = new ClassRoom(clsname);
// 선생님 정보를 console 화면을 통해 입력받아 Teacher 객체를 반환하는 메소드
Teacher teacher = scan.scanTeacher();
// teacher 객체를 ClassRoom에 저장
room.setTeacher(teacher);
// count번 반복하여 count명의 학생 정보를 입력 받는다.
for(int i=0; i < count; i++) {
Student student = scan.scanStudent(i+1);
room.addStudent(student);
}
room.print();
}
static public void testMakeClassRoom(int count) {
// 입력 테스트를 위한 유틸리티 클래스 객체를 생성하자.
ScanRoom scan = new ScanRoom();
// 학과 정보를 입력받아 ClassRoom에 저장한다.
// scanClassName => makeClassName 사용
ClassRoom room = new ClassRoom(scan.makeClassName());
// 선생님 정보를 입력받아 ClassRoom에 저장한다.
// scanTeacher => makeTeacher 사용
room.setTeacher(scan.makeTeacher());
// 5번 반복하여 5명의 학생 정보를 입력 받는다.
for(int i=0; i < count; i++) {
// scanStudent => makeStudent 사용
room.addStudent(scan.makeStudent());
}
room.print();
}
}