오버라이딩 선언되지 않은 자식클래스의 메소드를 호출하기 위해서는 명시적 객체 형변환을 사용하여 부모클래스의 참조변수로 자식클래스의 객체를 참조해 자식 클래스의 메소드를 호출해야한다.
하지만 상속관계가 아닌 클래스를 사용하여 명시적 객체 형변환을 할 경우 ClassCastException 에러가 발생한다.
해결하는 방법은 참조변수로 객체 형변환 가능한 클래스인지 확인 후 명시적 객체 형변환을 진행해야한다.
instanceof 연산자를 사용하여 참조변수가 형변환 가능한 클래스를 비교
형식) 참조변수 instanceof 클래스
참조변수로 객체 형변환 가능한 클래스가 아닌경우 [false]를 반환하고 객체 형변환 가능한 클래스인 경우 [true]를 제공하는 연산자
주로 조건문에서 사용한다
밑에 문제에서 사용한 방법
기존에 사용하던 방법은 각각의 객체를 저장하기 위한 요소를 가진 배열을 생성해서 저장해줬다면 부모클래스에 있는 배열을 생성하여 각 요소로 자식클래스가 가진 객체로 생성하여 집어넣으면 된다는 점이다.
AcademyPerson[] persons=new AcademyPerson[5];
//AcademyPerson 클래스(부모클래스)로 생성된 배열의 요소에는 학생정보(AcademyStudent 객체)
//, 강사정보(AcademyInstructor 객체), 직원정보(AcademyStaff 객체) 저장 가능
persons[0]=new AcademyStudent(1000, "홍길동", "웹개발자 과정");
persons[1]=new AcademyInstructor(2000, "임꺽정", "Java 과목");
persons[2]=new AcademyStaff(3000, "전우치", "운영관리팀");
persons[3]=new AcademyStudent(4000, "일지매", "웹디자인 과정");
persons[4]=new AcademyStaff(5000, "장길산", "경영회계팀");
사람정보(번호, 이름)를 저장하기 위한 클래스
학생, 강사, 직원에 대한 공통적인 속성과 행위를 구현하기 위해 작성
학생, 강사, 직원 관련 클래스가 상속받아야 되는 부모클래스
학생정보(학생번호, 학생이름, 수강과정)
강사정보(강사번호, 강사이름, 강의과목)
직원번호(직원번호, 직원이름, 근무부서)
package inheritance;
public class AcademyPerson {
private int id;
private String name;
// 부모클래스라면 무조건 매개변수가 없는 생성자를 가지고 있어야 됨
public AcademyPerson() {
}
public AcademyPerson(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 메소드
public void display() {
System.out.println("번호 = " + id);
System.out.println("이름 = " + name);
}
}
package inheritance;
public class AcademyStudent extends AcademyPerson {
// 자식클래스에서만 사용하는 필드
private String course;
// 생성자
public AcademyStudent(int id, String name, String course) {
super(id, name);
this.course = course;
}
// Getter & Setter
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
// 부모클래스에 있는 display() 메소드를 오버라이딩하여 재사용
@Override
public void display() {
System.out.println("학생번호 = " + getId());
System.out.println("학생이름 = " + getName());
System.out.println("수강과정 = " + course);
}
}
package inheritance;
public class AcademyInstructor extends AcademyPerson {
public String subject;
public AcademyInstructor(int id, String name, String subject) {
super(id, name);
this.subject = subject;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
// 오버라이딩
@Override
public void display() {
System.out.println("강사번호 = " + getId());
System.out.println("강사이름 = " + getName());
System.out.println("강의과목 = " + subject);
}
}
package inheritance;
public class AcademyStaff extends AcademyPerson {
private String depart;
public AcademyStaff(int id, String name, String depart) {
super(id, name);
this.depart = depart;
}
public String getDepart() {
return depart;
}
public void setDepart(String depart) {
this.depart = depart;
}
// 오버라이딩
@Override
public void display() {
System.out.println("직원번호 = " + getId());
System.out.println("직원이름 = " + getName());
System.out.println("근무부서 = " + depart);
}
}
package inheritance;
//학원인적자원(학생, 강사, 직원) 관리 프로그램 작성
public class AcademyApp {
public static void main(String[] args) {
/*
//학생정보(AcademyStudent 객체)를 저장하기 위한 요소를 가진 배열 생성
AcademyStudent[] students=new AcademyStudent[300];
//강사정보(AcademyInstructor 객체)를 저장하기 위한 요소를 가진 배열 생성
AcademyInstructor[] instructors=new AcademyInstructor[50];
//직원정보(AcademyStaff 객체)를 저장하기 위한 요소를 가진 배열 생성
AcademyStaff[] staffs=new AcademyStaff[100];
*/
//사람정보(AcademyPerson 객체)를 저장하기 위한 요소를 가진 배열 생성
AcademyPerson[] persons=new AcademyPerson[5];
//AcademyPerson 클래스(부모클래스)로 생성된 배열의 요소에는 학생정보(AcademyStudent 객체)
//, 강사정보(AcademyInstructor 객체), 직원정보(AcademyStaff 객체) 저장 가능
persons[0]=new AcademyStudent(1000, "홍길동", "웹개발자 과정");
persons[1]=new AcademyInstructor(2000, "임꺽정", "Java 과목");
persons[2]=new AcademyStaff(3000, "전우치", "운영관리팀");
persons[3]=new AcademyStudent(4000, "일지매", "웹디자인 과정");
persons[4]=new AcademyStaff(5000, "장길산", "경영회계팀");
//배열 요소에 저장된 부모클래스의 객체를 하나씩 제공받아 참조변수에 저장하여 부모클래스의
//객체를 참조하여 부모클래스의 메소드를 일괄적으로 호출하기 위한 반복문
for(AcademyPerson person : persons) {
// => instanceof 연산자 사용
// person이 AcademyStudent가 맞으면 조건 실행
if(person instanceof AcademyStudent) {
// 명시적 객체 형변환 진행
System.out.println(((AcademyStudent)person).getCourse()+"의 학생정보 >> ");
} else if(person instanceof AcademyInstructor) {
System.out.println(((AcademyInstructor)person).getSubject()+"의 강사정보 >> ");
} else if(person instanceof AcademyStaff) {
System.out.println(((AcademyStaff)person).getDepart()+"의 직원정보 >> ");
}
//오버라이딩 선언된 자식메소드의 메소드는 묵시적 객체 형변환에 의해 부모클래스의
//참조변수가 일시적으로 자식클래스의 객체를 참조해 자식클래스의 메소드 호출
// => 부모클래스의 참조변수는 상속관계의 자식클래스의 객체로 자동 형변환되어
//자식클래스의 객체를 참조해 자식클래스의 메소드 호출 - 오버라이딩에 의한 다형성
person.display();
System.out.println("==========================================================");
}
}
}