Java 19(abstract, final)

Kang.__.Mingu·2024년 5월 9일
0

Java

목록 보기
21/108

Abstract

  • 클래스 또는 메소드 작성시 사용할 수 있는 제한자

Abstract Class

  • 추상클래스(Abstract Class): abstract 제한자를 사용하여 작성된 클래스
  • 객체 생성이 목적이 아닌 상속을 목적으로 작성하기 위한 클래스

    형식) public abstract class 클래스명 { }

  • new 연산자로 클래스의 생성자를 호출하여 객체 생성시 에러 발생

Abstract Method

  • abstract 제한자를 사용하여 작성된 메소드

    형식) public abstract 반환형(자료형 변수명, 자료형 변수명, ...);

  • 메소드의 머릿부만 작성하고 몸체부가 없는 메소드 - 명령이 없는 메소드(미완성 메소드)
  • 자식클래스에서 반드시 오버라이딩 선언해야될 메소드를 제공하기 위한 사용 - 메소드 작성 규칙 제공
  • 자식클래스에서 추상메소드를 오버라이딩 선언하지 않으면 에러 발생
  • 추상메소드가 하나라도 작성된 클래스는 반드시 추상클래스로 선언

final

  • 클래스, 필드, 메소드 작성시 사용할 수 있는 제한자

final 클래스

  • final 제한자를 사용하여 작성된 클래스

    형식) public final class 클래스명 { }

  • 클래스를 상속받지 못하도록 제한하는 클래스

final 필드

  • final 제한자를 사용하여 작성된 필드

    형식) 접근제한자 final 자료형 필드명 = 초기값;

  • 필드에 저장된 초기값을 변경하지 못하도록 제한하는 필드
  • final 필드에 메소드를 오버라이드 선언하지 못하도록 제한하는 메소드

final 메소드

  • final 제한자를 사용하여 작성된 메소드

    형식) 접근제한자 final 반환형 메소드명(자료형 변수명, 자료형 변수명, ) {
    명령,
    명령;
    ...
    }


상수필드(Constant Field)

  • 값 대신 사용하기 위한 이름 제공 - 상수

    형식) public static final 자료형 상수필드명 = 값;

  • 상수필드명은 대문자로 사용하며 스네이크 표기법을 사용하여 작성

EmployeeApp (실행)

package inheritance;

//사원 급여 관리 프로그램 작성
public class EmployeeApp {
	public static void main(String[] args) {
		/*
		//Employee 클래스가 추상클래스로 선언되어 있는 경우 객체 생성시 에러 발생
		Employee employee=new Employee(1000, "홍길동");
		System.out.println("사원번호 = "+employee.getEmpNo());
		System.out.println("사원이름 = "+employee.getEmpName());
		*/
		
		/*
		//추상클래스로 참조변수를 생성하여 자식클래스의 객체를 저장 가능
		Employee employee1=new EmployeeRegular();
		Employee employee2=new EmployeeTime();
		Employee employee3=new EmployeeContract();
		*/
		
		//Employee 클래스를 상속받은 자식클래스의 객체를 저장할 수 있는 요소를 가진 배열 생성
		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).computeSalary());
			} else if(employee instanceof EmployeeTime) {
				System.out.println("사원급여 = "+((EmployeeTime)employee).computeTimePay());
			} else if(employee instanceof EmployeeContract) {
				System.out.println("사원급여 = "+((EmployeeContract)employee).computeConstract());
			} 
			*/ 

			//묵시적 객체 형변환에 의해 부모클래스의 참조변수가 일시적으로 자식클래스의 객체를
			//참조하여 자식클래스의 오버라이딩 선언된 메소드를 호출
			System.out.println("사원급여 = "+employee.computePay());
			System.out.println("인센티브 = "+employee.computeIncentive());
			System.out.println("==========================================================");
		}
	}
}

Employee (부모클래스)

public abstract class Employee {
    private int empNo;
    private String empName;
    // 상수필드(Constant Field): 값 대신 사용하기 위한 이름 제공 - 상수
    public static final double INCENTIVE_RATE = 1.5;
	
    // 부모클래스는 매개변수가 없는 생성자 생성해야됨
    public Employee() {
    }

    public Employee(int empNo, String empName) {
        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 abstract int computePay();

    // 모든 사원에게 사원듭여를 150%를 성과급으로 계산하여 반환하는 메소드
    // 문제점) 자식클래스에서 메소드를 오버라이딩 선언할 경우 부모클래스의 메소드는 숨겨지고
    // 자식클래스가 메소드가 호출되어 비정상적인 결과 발생
    // 해결법) final 제한자를 사용하여 메소드를 작성하면 자식클래스에 오버라이딩 선언 불가능
    public final int computeIncentive() {
        // 추상메소드를 호출하면 자동으로 자식클래스의 오버라이딩 선언된 메소드 호출
        return (int) (computePay() * INCENTIVE_RATE);
    }
}

EmployeeRegular (지식클래스 - 정규직)

package inheritance;

// 정규직 사원정보(사원번호, 사원이름, 연봉)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
// => 추상클래스를 상속받은 자식클래스는 추상클래스에 작성된 모든 추상메소드를 오버라이딩 선언
public class EmployeeRegular extends Employee {
    private int annualSalary;

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

    // 급여를 계산하여 반환하는 메소드
    // return 값이 있는 경우 void가 아닌 자료형으로 작성함
    @Override
    public int computePay() {
        return annualSalary / 12;
    }

    // 부모클래스의 final 메소드를 오버라이딩 선언한 경우 에러 발생
    /*
    @Override
    public int computeIncentive() {
        return super.computeIncentive();
    }
    */
}

EmployeeContract (자식클래스 계약직)

package inheritance;

// 계약직 사원정보(사원번호, 사원이름, 계약급여)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
public class EmployeeContract extends Employee {
    private int contractPay;

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

    @Override
    public int computePay() {
        return contractPay;
    }
}

EmployeeTime (자식클래스 - 시간제)

package inheritance;

// 시간제 사원정보(사원번호, 사원이름, 시급, 근무시간)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
public class EmployeeTime extends Employee {
    private int moneyPerHour;
    private int workedHour;

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

    // 급여를 계산하여 반환하는 메소드
    @Override
    public int computePay() {
        return moneyPerHour * workedHour;
    }
}
profile
최선을 다해 꾸준히 노력하는 개발자 망고입니당 :D

0개의 댓글