Java(26) - 다형성
1. 다형성이란
- 하나의 코드가 여러 자료형으로 구현되어 실행되는 것 (같은 코드에서 여러 실행 결과가 나옴)
- 정보은닉, 상속과 더불어 객체지향 프로그래밍의 가장 큰 특징 중 하나
- 객체지향 프로그래밍의 유연성, 재활용성, 유지보수성에 기본이 되는 특징
간단한 예시를 말로 하자면,
여러 클래스를 한 클래스에 상속시키고 사용시 참조변수 타입을 부모 클래스 타입으로
선언하고 인스턴스는 각 하위클래스로 생성, 메소드 오버라이딩을 활용해서 같은 메소드를
사용해 다양한 결과를 도출하는 것입니다.
다형성 예시
class Animal{
public void move() {
System.out.println("동물이 움직입니다.");
}
}
class Human extends Animal{
public void move() {
System.out.println("사람이 두 발로 걷습니다.");
}
public void readBook(){
System.out.println("사람이 책을 읽습니다.");
}
}
class Tiger extends Animal{
public void move() {
System.out.println("호랑이가 네 발로 뜁니다.");
}
public void hunting() {
System.out.println("호랑이가 사냥을 합니다.");
}
}
class Eagle extends Animal{
public void move() {
System.out.println("독수리가 하늘을 날아갑니다.");
}
public void flying() {
System.out.println("독수리가 멀리 날아갑니다.");
}
}
public class AnimalTest {
public static void main(String[] args) {
Animal hAnimal = new Human();
Animal tAnimal = new Tiger();
Animal eAnimal = new Eagle();
ArrayList<Animal> animalList = new ArrayList<Animal>();
animalList.add(hAnimal);
animalList.add(tAnimal);
animalList.add(eAnimal);
for(Animal animal : animalList) {
animal.move();
}
}
}
2. 다형성의 장점
- 다양한 여러 클래스를 하나의 자료형(상위클래스)으로 선언하거나,
형변환 하여 각 클래스가 동일한 메서드를 오버라이딩한 경우,
하나의 코드가 다양하게 구현을 실행할 수 있다. - 유사한 클래스가 추가되는 경우 유지보수에 용이하고,
각 자료형 마다 다른 메서드를 호출하지 않으므로 코드에서 많은 if문이 사라짐.
상속과 오버라이딩, 다형성을 한 맥락으로 이해하는 것이 중요합니다.
3. 상속은 언제 사용하는가
- IS-A 관계(is a relationship: inheritance)
- 일반적인(general) 개념과 구체적인(specific) 개념의 관계
- 단순히 재사용 목적이 아닙니다.
- HAS-A 관계(composition)
- 한 클래스가 다른 클래스를 소유한 관계
- 코드 재사용의 한 방법
IS-A 관계는 우리가 계속 공부해 온 상속 관계라고 생각하면 됩니다.
이 관계의 특징은
- 상속은 클래스간의 결합도가 높다.
- 상위 클래스의 수정이 많으면 하위 클래스에 영향이 미칠 수 있다.
- 계층 구조가 복잡하거나 hierarchy(계층)가 높으면 좋지 않다.
입니다.
HAS-A 관계 역시 상속의 조건에는 부합합니다.
상속의 기본 문법이 하위클래스가 상위클래스를 지니고 있기 때문입니다.
그러나 우리는 이 관계를 복합 관계로 이해하는게 일반적입니다.
(소유의 관계, 코드 재사용)
에시를 보겠습니다.
우선 상속을 이용한 코드를 보겠습니다.
class Gun{
int bullet; //장전된 총알의 수
public Gun(int bnum){bullet = bnum;}
public void shot(){
System.out.println("BBANG!");
bullet--;
}
}
class Police extends Gun{
int handcuffs; //소유한 수갑의 수
public Police(int bnum, int bcuff){
super(bnum);
handcuffs = bcuff;
}
public void putHandcuff(){
System.out.println("Snap!");
handcuffs--;
}
}
class HASInheritance{
public static void main(String[] args){
Police pman = new Police(5, 3);
pman.shot();
pman.putHandcuff();
}
}
위 코드는 HAS-A관계를 상속으로 표현한 것입니다.
다음은 HAS-A관게를 소유의 방식으로 표현한 코드를 보겠습니다.
class Gun{
int bullet; //장전된 총알의 수
public Gun(int bnum){bullet = bnum;}
public void shot(){
System.out.println("BBANG!");
bullet--;
}
}
class Police{
int handcuffs; //소유한 수갑의 수
Gun pistol; //소유하고 있는 권총
public Police(int bnum, int bcuff){
handcuffs = bcuff;
if(bnum != 0){
pistol = new Gun(bnum);
}else{
pistol = null;
}
}
public void putHandcuff(){
System.out.println("SNAP!");
handcuffs--;
}
public void shot(){
if(pistol == null){
System.out.println("Hut BBANG!");
}else{
pistol.shot();
}
}
}
class HasComposite{
public static void main(String[] args){
Police haveGun = new Police(5, 3);
haveGun.shot();
haveGun.putHandcuff();
Police dontHaveGun = new Police(0, 3);
dontHaveGun.shot();
}
}
코드의 양으로 봤을 때 지금은 소유의 관계의 코드가 더 많아보입니다.
하지만 이런 상황의 코드의 경우 상속으로 나타냈을 때 문제가 생길 수 있습니다.
- 권총을 소유하지 않은 경찰을 표현해야 할 때
- 권총, 수갑말고 다른 장비를 소유할 때
이런 경우를 반영하기 쉽지 않습니다.
즉 상속으로 이런 관계를 표현한 경우 두 클래스는 강한 연관성을 갖기 때문에
Gun 클래스를 상속받는 Police 클래스로는 총을 소유한 경찰만 표현이 가능합니다.
결론은 상속은 IS-A 관계의 표현에 매우 적절합니다.
그리고 경우에 따라서는 HAS-A 관계의 표현(소유 관계)에도 사용될 수 있으나,
프로그램의 변경에 제약이 생길 수 있습니다.
댓글남기기