→ 객체에 상관 없이 클래스로 접근하기 위해 사용하는 제한자
1.final 필드 - final 제한자를 사용하여 선언한 필드
형식) 접근제한자 final 자료형 필드명=값;
ex) Math 클래스 >> public static final double PI : 원주율을 제공하기 위한 상수
→ 필드에 저장된 값 변경 불가능 - 필드값을 변경할 경우 에러 발생
→ 필드 선언시 반드시 초기값이 저장되도록 설정
2.final 메소드 - final 제한자를 사용하여 선언한 메소드
형식) 접근제한자 final 반환형 메소드명(자료형 매개변수명,...) { 명령; ... }
→ Object 클래스 >> public final void notify()
→ 자식클래스에서 절대로 오버라이드 선언하지 못하도록 설정하는 메소드
3.final 클래스 - final 제한자를 사용하여 선언한 클래스
형식) public final class 클래스명 { }
→ ex) public final class System extends Object 클래스
→ 다른 클래스에서 상속 받을 수 없는 클래스
package inheritance;
//사원정보(사원번호,사원이름)를 저장하기 위한 클래스
// => 모든 사원 관련 클래스가 상속받아야 되는 부모클래스
// => 객체 생성이 목적이 아닌 상속이 목적인 클래스로 작성 - 추상클래스로 선언하는 것을 권장
//추상클래스(Abstract Class) : abstract 제한자를 사용하여 선언된 클래스
// => 객체 생성 불가능 - 상속 전용 클래스
// => 형식) public abstract class 클래스명 {}
//abstract 제한자 - 클래스, 메소드에 설정 가능한 제한자
public abstract class Employee {
private int empNo;
private String empName;
//상수필드(Constant Field) : 프로그램에서 값(리터럴) 대신 사용하기 위해
의미있는 단어로 제공되는 필드값
//형식) public static final 자료형 상수명=값;
// => 상수명은 대문자로 작성하며 스네이크 표기법을 이용하여 작성하는 것을 권장
public static final double INCENTIVE_RATE=1.5;
public Employee() {
// TODO Auto-generated constructor stub
}
public Employee(int empNo, String empName) {
super();
this.empNo = empNo;
this.empName = empName;
}
public int getEmpNo() {
return empNo;
}
public void setEmpNo(int empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
/*
//급여를 계산하여 반환하는 메소드
//자식클래스에서 부모클래스의 메소드를 오버라이드 선언하지 않아도 에러 미발생
// => 자식클래스에서 메소드를 오버라이드 선언하지 않은 경우 부모클래스의
메소드 호출 - 비정상적인 결과 발생
public int computePay() {
return 0;
}
*/
//자식클래스에서 부모클래스의 메소드를 무조건 오버라이드 선언되도록 설정하기
위해 추상메소드로 선언
//추상메소드(Abstract Method) : abstract 제한자를 사용하여 선언된 메소드
// => 메소드의 머릿부만 작성하고 몸체부는 작성하지 않는 미완성된 메소드
//형식) 접근제한자 abstract 반환형 메소드명(자료형 매개변수명,...);
// => 추상메소드가 선언된 클래스는 무조건 추상클래스로 선언
public abstract int computePay();
//인센티브를 계산하여 반환하는 메소드
// => 모든 사원에게 급여의 150%를 인센티브로 제공되도록 계산
//자식클래스에서 메소드를 오버라이드 선언하면 비정상적인 결과값 반환
// => 자식클래스에서 메소드를 오버라이드 선언하지 못하도록 final 메소드로 선언
public final int computeIncentive() {
//추상메소드를 호출한 경우 묵시적 객체 형변환에 의해 자식클래스의
메소드 호출
//return (int)(computePay()*1.5);
return (int)(computePay()*INCENTIVE_RATE);
}
}
============================================================
package inheritance;
//사원 급여 관리 프로그램
public class EmployeeApp {
public static void main(String[] args) {
//추상클래스로 객체를 생성할 경우 에러 발생
//Employee employee=new Employee();
//추상클래스(부모클래스)로 참조변수를 생성하여 모든 자식클래스의 객체 저장 가능
//Employee employee1=new EmployeeRegular();
//Employee employee2=new EmployeeTime();
//Employee employee3=new EmployeeContract();
//모든 사원정보를 저장할 수 있는 참조요소가 존재하는 배열 생성
Employee[] empArray=new Employee[5];
empArray[0]=new EmployeeRegular(1000, "홍길동", 96000000);
empArray[1]=new EmployeeTime(2000, "임꺽정", 50000, 150);
empArray[2]=new EmployeeContract(3000, "전우치", 7000000);
empArray[3]=new EmployeeTime(4000, "일지매", 20000, 100);
empArray[4]=new EmployeeRegular(5000, "장길산", 60000000);
for(Employee employee:empArray) {
System.out.println("사원번호 = "+employee.getEmpNo());
System.out.println("사원이름 = "+employee.getEmpName());
/*
//사원의 급여를 반환받아 출력
// => 참조변수는 부모클래스의 객체만 참조 가능하므로 자식클래스의
메소드 호출 불가능
// => 명시적 객체 형변환을 사용하여 참조변수로 자식클래스의 객체를
참조하여 메소드 호출 가능
// => instanceof 연산자를 사용하여 자식클래스를 구분하여 객체 형변환 -
ClassCastException 발생 방지
if(employee instanceof EmployeeRegular) {
System.out.println("급여 = "+
((EmployeeRegular)employee).computeRegular());
} else if(employee instanceof EmployeeTime) {
System.out.println("급여 = "+
((EmployeeTime)employee).computeTime());
} else if(employee instanceof EmployeeContract) {
System.out.println("급여 = "+
((EmployeeContract)employee).computeContract());
}
*/
//자식클래스에서 부모클래스의 메소드를 오버라이드 선언하면 묵시적 객체
형변환에 의해 자동으로 참조변수가 자식클래스로 형변환되어 자식클래스의
메소드 호출 가능
System.out.println("급여 = "+employee.computePay());
//사원의 인센티브를 반환받아 출력
System.out.println("인센티브 = "+employee.computeIncentive());
System.out.println("==================================================");
}
}
}
package inheritance;
//정규직 사원정보(사원번호,사원이름,연봉)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
public class EmployeeRegular extends Employee {
private int annualSalary;
public EmployeeRegular() {
// TODO Auto-generated constructor stub
}
public EmployeeRegular(int empNo, String empName, int annualSalary) {
super(empNo, empName);
this.annualSalary = annualSalary;
}
public int getAnnualSalary() {
return annualSalary;
}
public void setAnnualSalary(int annualSalary) {
this.annualSalary = annualSalary;
}
//급여를 계산하여 반환하는 메소드
public int computeRegular() {
return annualSalary/12;
}
//추상메소드가 선언된 추상클래스를 상속받은 자식클래스에서는 반드시 부모클래스의 모든
//추상메소드를 무조건 오버라이드 선언 - 오버라이드 선언하지 않은 경우 에러 발생
// => 추상메소드를 오버라이드 선언하지 않은 자식클래스는 추상클래스로 설정 가능 - 비권장
@Override
public int computePay() {
return annualSalary/12;
}
/*
//부모클래스의 final 메소드를 자식클래스에서 오버라이드 선언한 경우 에러 발생
@Override
public int computeIncentive() {
return 100000000;
}
*/
}
package inheritance;
//시간제 사원정보(사원번호,사원이름,시급,근무시간)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
public class EmployeeTime extends Employee {
private int moneyPerHour;
private int workedHour;
public EmployeeTime() {
// TODO Auto-generated constructor stub
}
public EmployeeTime(int empNo, String empName, int moneyPerHour, int workedHour) {
super(empNo, empName);
this.moneyPerHour = moneyPerHour;
this.workedHour = workedHour;
}
public int getMoneyPerHour() {
return moneyPerHour;
}
public void setMoneyPerHour(int moneyPerHour) {
this.moneyPerHour = moneyPerHour;
}
public int getWorkedHour() {
return workedHour;
}
public void setWorkedHour(int workedHour) {
this.workedHour = workedHour;
}
//급여를 계산하여 반환하는 메소드
public int computeTime() {
return moneyPerHour*workedHour;
}
@Override
public int computePay() {
return moneyPerHour*workedHour;
}
}
package inheritance;
//계약직 사원정보(사원번호,사원이름,계약급여)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
public class EmployeeContract extends Employee {
private int contractPay;
public EmployeeContract() {
// TODO Auto-generated constructor stub
}
public EmployeeContract(int empNo, String empName, int contractPay) {
super(empNo, empName);
this.contractPay = contractPay;
}
public int getContractPay() {
return contractPay;
}
public void setContractPay(int contractPay) {
this.contractPay = contractPay;
}
//급여를 계산하여 반환하는 메소드
public int computeContract() {
return contractPay;
}
@Override
public int computePay() {
return contractPay;
}
}