사전적 의미
- 여러 다른 형태로 발생하는 조건
프로그래밍
- 루틴이 서로 다른 시간에 서로 다른 유형의 타입 사용할 수 있도록 하는 기능
직원과 매니저의 관계
현실
- 매니저는 직원에게 일을 하나하나 간섭하여 시키고 알려준다.
- 직원은 매니저를 욕하며 일한다. (넝~담!)
프로그램
- 매니저는 직원에게 일만 시킴 → 무슨일을 하는지 모름!
- 직원은 일을 함 → 자율적으로 일한다
구현 코드
public class Manager {
private List<Employee> employees = new ArrayList<>();
public void orderToDoJop() {
for (Employee employee : employees) {
if (employee != null) {
employee.work();
}
}
}
public void addEmployee(Employee employee) {
if (employee != null) {
employees.add(employee);
}
}
}
Manager 클래스는 고용한 직원을 추가해주고 직원에게 일을 시킨다.
public abstract class Employee {
public abstract void work();
}
Employee 클래스는 추상적이다. 무슨 일을 하는 직원인지 확인이 안된다. 무슨 일을 하는지를 범주에 넣고 분류를 해보면 예를 들어 Hall, Kitchen 이라는 2가지의 클래스가 분류된다.
public class Hall extends Employee {
@Override
public void work() {
System.out.println("테이블 정리");
}
}
public class Kitchen extends Employee{
@Override
public void work() {
System.out.println("음식 만들기");
}
}
Employee 추상 클래스를 상속한 클래스에게 책임을 위임 시켰다.
public class Main {
public static void main(String[] args) {
Employee hall = new Hall();
Employee kitchen = new Kitchen();
Manager manager = new Manager();
manager.addEmployee(hall);
manager.addEmployee(kitchen);
manager.orderToDoJop();
}
}
메인 클래스를 살펴보면 매니저와 직원을 생성하고 매니저는 직원을 고용한다. 그리고 직원에게 일을 시킨다. 내부적으로 볼때 매니저는 직원이 하는일을 정확히 모르는데 Hall 과 Kitchen은 알아서 자기 할 일을 한다.
이것이 다형성의 아주 큰 장점이고, 객체가 하는 일을 간섭하지 않고 자율적이게 활동 할 수 있게 해주는 객체 지향 프로그래밍의 좋은점이다!
정적 다형성 and 동적 다형성
위에서 다형성이란 루틴이 서로 다른 시간에 서로 다른 유형의 타입 사용할 수 있도록 하는 기능이라 설명했다.
서로 다른 시간이란 컴파일(정적) 과 런타임(동적) 을 말한다.
정적 다형성 (오버로딩)
정적 다형성이란 다형성을 모방한 것인데 컴파일 시간에 동작이 된다.
ArrayList의 add() 메서드를 정적 다형성의 예로 들수 있습니다. object를 받는 메서드와 인덱스를 받고 object도 받는 삽입 메서드가 있다. 이 둘은 메서드 명이 같고 단지 매개변수만 다를 뿐이다.
이는 컴파일 시점에서 컴파일러가 매개변수 타입과 갯수가 일치하는 메서드명을 찾아 컴파일 해준다.
결국엔 오버로딩과 같은 말이다.
동적 다형성
동적 다형성이란 런타임 시점에 인스턴스는 힙메모리 영역에 할당된다. 힙 영역에 올라간 인스턴스는 상위 형식에 할당될 때 적절한 메서드를 찾아 처리한다.
예제 코드
public abstract class Employee {
public void wellCome() {
System.out.println("어서오세요!");
}
}
직원의 wellCome() 기능을 구현하였다.
public class Hall extends Employee {
public void wellCome() {
System.out.println("몇분이세요?");
}
}
홀직원에게도 메서드 시그니처는 같지만 내부 로직은 다르게 구현했다.
Employee kitchen = new Kitchen();
Employee hall = new Hall();
hall.wellCome();
kitchen.wellCome();
출력
//몇분이세요?
//어서오세요!
콘솔에 서로 다른 로직이 출력 될 것이다.
업캐스팅 and 다운캐스팅
- 업캐스팅
하위클래스에서 상위클래스로 변환하는 것을 업캐스팅이라 말한다.
생략 가능함 → 컴파일러가 생략 가능하게 해준다.
- 다운캐스팅
상위클래스에서 하위클래스로 변환하는 것을 다운 캐스팅이라 말한다.
Dog dog = new Dog(); // 상위 클래스
JindoDog jindoDog = new JindoDog(); // 하위 클래스
dog = (Dog) jindoDog; // 업캐스팅
jindoDog = (JindoDog) dog; // 다운캐스팅
위와 같은 코드는 상위 하위 관계를 정확히 알아서 캐스딩을 했지만 실제 개발환경에서는 타입 체킹을 해야한다. 타입 체킹을 하지 않고 형변환을 해버리면 컴파일 에러로 잡아주긴하지만 컴파일이 다 잡아준다는 보장은 없다.
그러므로 타입 체킹을 할 수 있는 instanceof 연산자로 타입 체킹을 해줘야 한다.
if (jindoDog instanceof Dog) {
dog = (Dog) jindoDog;
}
다형성의 원리를 알면 인터페이스와 추상클래스를 잘 이해할 수 있을 것이다. 그리고 디자인 패턴인 템플릿 메서드 패턴도 이해할 수 있을 것이다.
'Laguage' 카테고리의 다른 글
[Java] Generic Programing (0) | 2022.07.14 |
---|---|
[Java] Inheritance in Java (0) | 2022.07.09 |
[Java] Java Interface (0) | 2022.07.01 |
[Java] Abstract Classes in Java (0) | 2022.07.01 |
[Java] Java 에서 파일을 읽는 여러가지 방법 (0) | 2022.06.26 |
[Java] What is Serialization in Java? (0) | 2022.06.24 |
[Java] ArchUnit 아키텍처 테스트에 대해 알아보자 (0) | 2022.06.18 |
[JAVA] JVM 구조 (0) | 2022.02.11 |