package ex_type_casting;
public class Ex1 {
public static void main(String[] args) {
/*
* instanceof 연산자
*
* < 기본 문법 >
* boolean 변수명 = a instanceof B
* => a : 객체(참조변수)
* => B : 클래스타입
*/
Parent p = new Parent();
// if문을 사용하여 Parent 객체가 Child 타입으로 변환 가능 여부 판별
// => p is a Child에 대한 판별 수행
if (p instanceof Child) {
// 판별 결과가 true이면 무조건 Child 타입으로 변환 가능
System.out.println("p -> Child 타입으로 형변환 가능!");
} else {
// 판별 결과가 false이면 어떠한 변환도 불가능
System.out.println("p -> Child 타입으로 형변환 불가능!");
}
System.out.println("===================================");
Parent p2 = new Child(); // 업캐스팅
// if문을 사용하여 p2 객체가 Child 타입으로 변환 가능 여부 판별
if (p2 instanceof Child) {
// 판별 결과가 true 이면 무조건 Child 타입으로 변환 가능
System.out.println("p2 -> Child 타입으로 형변환 가능!");
// => 서브클래스를 이미 업캐스팅 해 놓은 상태이므로 형변환 가능하다는 true 리턴
// Child c = p2; // 자동형변환은 불가능한 관계
Child c = (Child) p2; // 강제형변환
} else {
// false이면 변환 불가능
System.out.println("p2 -> Child 타입으로 형변환 불가능!");
}
System.out.println("=============================");
// SmartPhone 인스턴스 생성
SmartPhone 내폰 = new SmartPhone();
// 내폰은 SmartPhone 입니까? true
if (내폰 instanceof SmartPhone) {
System.out.println("내폰은 SmartPhone 이다!");
// 그러므로 SmartPhone 타입 변수에 저장 가능
SmartPhone 동생폰 = 내폰;
동생폰.call();
동생폰.sms();
동생폰.kakaoTalk();
동생폰.youtube();
} else {
System.out.println("내폰은 SmartPhone 아니다!");
}
System.out.println("=================================");
// 내폰은 HandPhone 입니까?
if (내폰 instanceof HandPhone) {
System.out.println("내폰은 HandPhone 이다!");
System.out.println("그러므로 HandPhone으로 형변환 가능!");
HandPhone 엄마폰 = 내폰; // 업캐스팅
엄마폰.call();
엄마폰.sms();
// 엄마폰.kakaoTalk(); // 오류 발생! 참조영역 축소!
} else {
System.out.println("내폰은 HandPhone 아니다!");
}
System.out.println("=================================");
HandPhone 엄마폰 = new HandPhone();
// 엄마폰은 SmartPhone 입니까?
if (엄마폰 instanceof SmartPhone) {
System.out.println("엄마폰은 SmartPhone 이다!");
} else {
System.out.println("엄마폰은 SmartPhone이 아니다!");
// SmartPhone 내폰2 = 엄마폰; // 다운캐스팅 필요!
// SmartPhone 내폰2 = (SmartPhone) 엄마폰; // 실행 시 오류 발생!
}
System.out.println("=================================");
HandPhone 엄마폰2 = new SmartPhone(); // 업캐스팅
if (엄마폰2 instanceof SmartPhone) {
System.out.println("엄마폰2는 SmartPhone 이다!");
// SmartPhone 내폰2 = 엄마폰2; // 강제형변환 필요
SmartPhone 내폰2 = (SmartPhone) 엄마폰2;
내폰2.call();
내폰2.sms();
내폰2.kakaoTalk();
내폰2.youtube();
} else {
System.out.println("엄마폰2는 SmartPhone 아니다!");
}
}
}
class Parent {}
class Child extends Parent {}
class HandPhone {
public void call() {
System.out.println("HandPhone의 전화 기능!");
}
public void sms() {
System.out.println("HandPhone의 문자 기능!");
}
}
// SmartPhone 클래스 정의 - HandPhone 클래스 상속
class SmartPhone extends HandPhone {
public void kakaoTalk() {
System.out.println("SmartPhone의 카톡 기능!");
}
public void youtube() {
System.out.println("SmartPhone의 유튜브 기능!");
}
}
연습
package ex_type_casting;
public class Test1 {
public static void main(String[] args) {
Employee emp = new Employee("1111", "홍길동", 4000);
System.out.println("Employee");
emp.calcSalary();
Manager man = new Manager("2222", "이순신", 5000, "영업팀");
System.out.println("Manager");
man.calcSalary();
Engineer eng = new Engineer("3333", "강감찬", 3000, 3);
System.out.println("Engineer");
eng.calcSalary();
}
}
/*
* 사원(Employee) 클래스
* 멤버변수 : 사원번호(id, 문자열), 사원이름(name, 문자열), 연봉(salary, 정수)
* 사원번호, 이름, 연봉을 전달받아 초기화하는 생성자 정의
* 사원 정보(사원번호, 이름, 연봉)를 문자열로 결합하여 리턴하는 getEmployee() 메서드 정의
*
* 매니저(Manager) 클래스 - Employee 클래스 상속
* 멤버변수 : 관리부서명(depart, 문자열)
* 사원번호, 이름, 연봉, 관리부서명을 전달받아 초기화하는 생성자 정의
* 사원 정보(사원번호, 이름, 연봉, 관리부서명)을 문자열로 결합하여 리턴하는
* getEmployee() 메서드 오버라이딩
*
* 엔지니어(Engineer) 클래스 정의 - Employee 클래스 상속
* 멤버변수 : 자격증 갯수(certCount, 정수)
* 사원번호, 이름, 연봉, 작겨증 갯수를 전달받아 초기화하는 생성자 정의
* 사원 정보(사원번호, 이름, 연봉, 자격증 갯수)를 문자열로 결합하여 리턴하는
* getEmployee() 메서드 오버라이딩
*
*/
class Employee {
String id;
String name;
int salary;
// 사원번호와 이름, 연봉을 전달받아 초기화하는 생성자 Employee() 정의
public Employee(String id, String name, int salary) {
super();
this.id = id;
this.name = name;
this.salary = salary;
}
// 사원 전보를 문자열로 결합하여 리턴하는 getEmployee() 메서드 정의
public String getEmployee() {
return id + ", " + name + ", " + salary;
}
// 1. 메서드 오버라이딩을 통해 각 클래스에서 따로 연봉 계산할 경우
// 연봉을 계산하는 calcSalary() 메서드 정의
public void calcSalary() {
System.out.println("연봉 : " + salary);
}
// 2. 슈퍼클래스인 Employee 에서 모든 직원 연봉을 다 계산할 경우
// => 메서드 하나로 Employee, Manager, Engineer 인스턴스를 모두 전달받아야 하므로
// 업캐스팅 활용
public void calcSalary(Employee emp) {
// Employee 타입으로 업캐스팅 할 경우
// Manager, Engineer 클래스에 선언된 멤버에 접근이 불가능해짐
// => Employee에서 상속된 공통 멤버에만 접근 가능
// 따라서 다운캐스팅을 통해 상세 멤버에 접근할 수 있어야 함
// => instanceof 연산자를 사용하여 Employee, Manger, Engineer 판별
// 주의사항!
// instanceof 연산자를 사용하여 형변환 가능 여부 판별 시
// 슈퍼클래스 타입보다 서브클래스 타입을 먼저 판별!!
if (emp instanceof Engineer) {
// 엔지니어의 연봉 계산 => 다운캐스팅 필요
Engineer e = (Engineer) emp;
System.out.println("자격증 갯수 : " + e.certCount + "에 따른 연봉 계산");
// ex) certCount 갯수 * 10만원의 보너스 추가
System.out.println("엔지니어의 연봉 : " + salary);
} else if (emp instanceof Manager) {
}else if (emp instanceof Employee) {
}
}
}
// 매니저 클래스
class Manager extends Employee {
String depart;
public Manager(String id, String name, int salary, String depart) {
super(id, name, salary); // 슈퍼클래스의 생성자를 호출하여 대신 초기화
// this.id = id;
// this.name = name;
// this.salary = salary;
// => 슈퍼클래스 Employee에 기본 생성자가 없으므로 파라미터 생성자를 명시적으로
// 호출하지 않으면 오류 발생!
this.depart = depart;
}
@Override
public String getEmployee() {
return super.getEmployee() + ", " + depart;
// => 오버라이딩으로 인해 은닉된 슈퍼클래스의 메서드를 호출하라면
// 레퍼런스 super를 통해 접근
// return id + ", " + name + ", " + salary + ", " + depart; // 동일한 문장
}
// 1. 메서드 오버라이딩을 통해 각 클래스에서 따로 연봉 계산할 경우
@Override
public void calcSalary() {
System.out.println("관리 부서 : " + depart + " 에 따른 연봉 계산");
// ex) depart 가 "영업팀" 일 경우 보너스 50% 향상 등 수행
System.out.println("매니저의 연봉 : " + salary);
}
}
class Engineer extends Employee {
int certCount;
public Engineer(String id, String name, int salary, int certCount) {
super(id, name, salary);
this.certCount = certCount;
}
@Override
public String getEmployee() {
return super.getEmployee() + ", " + certCount;
}
// 1. 메서드 오버라이딩을 통해 각 클래스에서 따로 연봉 계산할 경우
@Override
public void calcSalary() {
System.out.println("자격증 갯수 : " + certCount + "에 따른 연봉 계산");
// ex) certCount 갯수 * 10만원의 보너스 추가
System.out.println("엔지니어의 연봉 : " + salary);
}
}