09009
[Java] 다형성, 오버라이딩 (1) 본문
다형성
• 하나의 인터페이스를 사용하여 다양한 구현 방법을 제공
• 하나의 클래스나 함수가 다양하게 동작하는 것
• 하나의 참조변수로 여러 타입의 객체를 참조할 수 있는 것
- 조상클래스 타입의 참조변수로 자손 클래스의 인스턴스 참조 가능
오버라이딩
• 조상클래스로부터 상속받은 메서드의 내용을 상속받는 클래스에 맞게 변경하는 것
오버라이딩의 조건
• 선언부(이름, 매개변수, 반환타입)가 같아야 한다.
• 조상 클래스를 오버라이딩하는 자손 클래스의 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
- 조상 클래스에 있는 메서드의 접근 제어자가 protected라면,
이를 오버라이딩하는 자손 클래스에 정의된 메서드의 접근 제어자는 범위가 같거나 넓은 protected이거나 public이어야 한다.
• 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
오버라이딩의 예시
✍ Shape.java
package ch08;
public class Shape {
void draw() {
System.out.println("그린다");
}
}
class Rectangle extends Shape {
void draw() {
System.out.println("사각형을 그린다");
}
}
class Triangle extends Shape {
void draw() {
System.out.println("삼각형을 그린다");
}
}
class Circle extends Shape {
void draw() {
System.out.println("원을 그린다");
}
}
✍ ShapeEx.java
package ch08;
// !!! 중요 !!!
//오버로딩: 같은 클래스, 생성자/메서드, 매개변수의 갯수가 다르거나 데이터형이 달라야 한다
//오버라이딩: 상속 관계, 메서드, 반환형, 매개변수 갯수, 이름, 데이터형이 일치
// 부모보다 접근지정자의 범위가 같거나 넓어야 한다 -> 다형성
public class ShapeEx {
public static void main(String[] args) {
Shape[] sh = new Shape[3];
sh[0] = new Rectangle();
sh[1] = new Triangle();
sh[2] = new Circle();
// draw()라는 메서드를 원/사각형/삼각형 그린다로 다양하게 표현하는 것을 다형성
for(int i = 0 ; i < sh.length; i++) {
sh[i].draw();
}
}
}
💻 출력 결과
사각형을 그린다
삼각형을 그린다
원을 그린다
위의 소스코드에서 확인할 수 있듯이 draw()라는 메서드를 원/사각형/삼각형 그린다로 다양하게 표현하는 것을 다형성이라고한다.
!!! (중요) 오버로딩과 오버라이딩 !!!
오버로딩
• 기존에 없는 새로운 메서드를 정의하는 것
• 같은 클래스에서 생성자, 메서드, 매개변수의 개수가 다르거나 데이터형이 달라야한다.
오버라이딩
• 상속받은 메서드의 내용을 변경하는 것
• (상속 관계) 메서드명, 반환형, 매개변수 개수, 이름, 데이터형이 일치한다.
• 자식은 부모보다 접근지정자의 범위가 같거나 넓어야 한다.
class 앞에 final을 붙일 경우
• final을 class 앞에 작성하면 상속을 안하겠다는 것으로 간주한다.
• final을 메서드 앞에 작성하면 오버라이딩이 금지된다.
아래에 작성된 코드는 작성 시 빨간 줄이 그어지는 에러가 발생한다.
- 에러 발생 소스코드
• 위의 소스코드를 참고하면 Over2 클래스가 상속받으려는 Over1 클래스 이름 앞에 final이 작성되어 있기 때문에 상속이 금지되어 에러가 발생한다.
• 메서드도 마찬가지로 Over2 클래스가 오버라이딩하려는 Over1 클래스에 있는 m1() 메서드도 앞에 final이 작성되어 있기 때문에 오버라이딩이 금지되어 에러가 발생한다.
아래와 같이 상속과 오버라이딩이 올바르게 된 코드를 살펴보자.
✍ 입력
class Over1 {
void m1() {
System.out.println("부모 메서드입니다.");
}
}
class Over2 extends Over1 {
@Override // 오버라이딩: 자식 클래스에서 부모의 메서드를 재정의한다.
void m1() {
System.out.println("자식 메서드입니다.");
}
}
public class Over1Ex {
public static void main(String[] args) {
Over1 o1 = new Over1();
Over1 o2 = new Over2(); // 부모(Over1) 선언, 자식(Over2) 생성
o1.m1(); o2.m1();
}
}
💻 출력 결과
부모 메서드입니다.
자식 메서드입니다.
실습 예제
총 5명에 대하여 급여 계산, 보너스 계산
-----출력형식-----
xxx의 급여명세서
급여: xx
보너스 : xx
✍ Employee.java
public class Employee {
public final static double INCENTIVE_RATE = 0.1; // final: 바꾸지 않겠다는 뜻, 인센티브는 10%로 고정
private String name;
Employee() {
}
public String getName() {
return name;
}
Employee(String name) {
this.name = name;
}
int computePay() { // 재정의해서 사용할 예정
return 0;
}
final int computeIncentive() { // final : 재정의 (overriding) 금지
int result = 0;
int pay = computePay();
if (pay >= 10000) result = (int) (pay * INCENTIVE_RATE);
return result;
}
}
✍ SalaryMan.java
public class SalaryMan extends Employee {
private int annualSalary;
SalaryMan(String name, int annualSalary) {
super(name); this.annualSalary = annualSalary;
}
int computePay() {
return annualSalary / 12;
}
// computeIncentive() { // 재정의(overriding) 금지 final은 재정의 금지
}
✍ HourlyEmployee.java
public class HourlyEmployee extends Employee {
private int hourWorked;
private int moneyPerHour;
HourlyEmployee(String name, int hourWorked, int moneyPerHour) {
super(name); this.hourWorked = hourWorked; this.moneyPerHour = moneyPerHour;
}
int computePay() {
return hourWorked * moneyPerHour;
}
}
✍ EmployeeEx.java
public class EmployeeEx {
public static void main(String[] args) {
Employee[] emps = new Employee[5];
emps[0] = new SalaryMan("홀란드", 2000000);
emps[1] = new SalaryMan("음바페", 3000000);
emps[2] = new HourlyEmployee("외데고르", 100, 800);
emps[3] = new HourlyEmployee("비니시우스", 200, 20000);
emps[4] = new HourlyEmployee("그릴리쉬", 300, 10000);
for(Employee emp : emps) {
int sal = emp.computePay();
int bonus = emp.computeIncentive();
System.out.println("***** " + emp.getName() + "의 급여명세서 *****");
System.out.println("급여 : " + sal);
System.out.println("보너스 : " + bonus);
}
}
}
💻 출력
***** 홀란드의 급여명세서 *****
급여 : 166666
보너스 : 16666
***** 음바페의 급여명세서 *****
급여 : 250000
보너스 : 25000
***** 외데고르의 급여명세서 *****
급여 : 80000
보너스 : 8000
***** 비니시우스의 급여명세서 *****
급여 : 4000000
보너스 : 400000
***** 그릴리쉬의 급여명세서 *****
급여 : 3000000
보너스 : 300000
//
'Back-End > JAVA' 카테고리의 다른 글
[Java] collection (0) | 2023.03.11 |
---|---|
[Java] Object 클래스, equals(), toString() (2) | 2023.03.11 |
[Java] 클래스 간의 관계 - 포함관계 (0) | 2023.03.11 |
[Java] 상속 (0) | 2023.03.11 |
[Java] 메서드 (0) | 2023.03.10 |