달나라 노트

Java - Polymorphism 본문

Java

Java - Polymorphism

CosmosProject 2021. 3. 14. 21:54
728x90
반응형

 

 

 

 

original source = www.w3schools.com  

 

 

한번 동물의 울음소리를 출력해주는 코드를 작성해봅시다.

 

class Animal {

}

class Cat extends Animal {

}

class Lion extends Animal {

}

class Dog extends Animal {

}

class Bark {
    public void bark(Animal animal) {
        if (animal instanceof Cat) {
            System.out.println("Cat sounds 야옹.");
        }
        else if (animal instanceof Lion) {
            System.out.println("Lion sounds 어흥.");
        }
        else if (animal instanceof Dog) {
            System.out.println("Dog sounds 멍멍.");
        }
    }
}

public class JavaPrac {
    public static void main(String args[]) {
        Bark bark = new Bark();

        Cat cat = new Cat();
        Lion lion = new Lion();
        Dog dog = new Dog();

        bark.bark(cat);
        bark.bark(lion);
        bark.bark(dog);
    }
}


-- Result
Cat sounds 야옹.
Lion sounds 어흥.
Dog sounds 멍멍.

위 코드에서 봐야 할 점이 몇 가지 있습니다.

 

 

 

 

 

 

class Bark {
    public void bark(Animal animal) {
        if (animal instanceof Cat) {
            System.out.println("Cat sounds 야옹.");
        }
        else if (animal instanceof Lion) {
            System.out.println("Lion sounds 어흥.");
        }
        else if (animal instanceof Dog) {
            System.out.println("Dog sounds 멍멍.");
        }
    }
}

위 부분을 봅시다.

Bark class 속에 bark method를 만들고 있습니다.

그리고 bark method의 parameter는 Animal animal입니다.

이것은 method의 parameter로 Animal class 또는 Animal class를 상속받은 어떤 다른 class가 주어져야 한다는 뜻입니다.

 

그리고 bark method를 보면 조건문이 있습니다.

각각의 부분을 살펴보면 다음과 같습니다.

bark(Animal animal) -> Animal class로 만들어진 animal 객체를 parameter로 받음.

(animal instanceof Cat) -> animal 객체와 Cat 객체가 동일하거나, animal 객체의 부모 class인 Animal class를 상속받은 class가 Cat class일 경우 true를 반환.

 

* A(object) instanceof B(class) = A 객체가 B class와 동일하거나, A가 부모 class이고 B가 자식 class 관계이면 true를 반환합니다. 부모는 자식을 품을 수 있기 때문입니다.

 

 

 

class Bark {
    public void bark(Animal animal) {
        if (animal instanceof Cat) {
            System.out.println("Cat sounds 야옹.");
        }
        else if (animal instanceof Lion) {
            System.out.println("Lion sounds 어흥.");
        }
        else if (animal instanceof Dog) {
            System.out.println("Dog sounds 멍멍.");
        }
    }
}

public class JavaPrac {
    public static void main(String args[]) {
        Bark bark = new Bark();

        Cat cat = new Cat();
        Lion lion = new Lion();
        Dog dog = new Dog();

        bark.bark(cat);
        bark.bark(lion);
        bark.bark(dog);
    }
}

main method를 보면 Bark, Cat, Lion, Dog class를 가지고 각각의 객체를 생성하고 있습니다.

 

그리고 bark 객체에 각각의 동물 객체(Cat, Lion, Dog)를 전달하여 동물별로 설정된 울음소리를 출력하고 있습니다.

 

여기까진 문제가 없습니다.

 

근데 만약 위 리스트에 돼지, 까마귀, 기린(?) 등의 울음소리를 추가해야하는 상황이 왔다고 가정합시다.

 

class Animal {

}

class Cat extends Animal {

}

class Lion extends Animal {

}

class Dog extends Animal {

}

class Pig extends Animal { // 추가됨

}

class Bark {
    public void bark(Animal animal) {
        if (animal instanceof Cat) {
            System.out.println("Cat sounds 야옹.");
        }
        else if (animal instanceof Lion) {
            System.out.println("Lion sounds 어흥.");
        }
        else if (animal instanceof Dog) {
            System.out.println("Dog sounds 멍멍.");
        }
        else if (animal instanceof Pig) { // 추가됨
        	System.out.println("Pig sounds 꿀꿀.");
        }
    }
}

public class JavaPrac {
    public static void main(String args[]) {
        Bark bark = new Bark();

        Cat cat = new Cat();
        Lion lion = new Lion();
        Dog dog = new Dog();
        Pig pig = new Pig(); // 추가됨

        bark.bark(cat);
        bark.bark(lion);
        bark.bark(dog);
        bark.bark(pig); // 추가됨
    }
}


-- Result
Cat sounds 야옹.
Lion sounds 어흥.
Dog sounds 멍멍.
Pig sounds 꿀꿀.

수정본을 보면 위와 같을 것입니다.

추가된 부분을 주석으로 표시해놨습니다.

 

Pig class를 추가하고,

Bark class의 조건문에 Pig를 추가하고

main method에 pig 객체를 생성하고

bark method에 pig를 전달해야합니다.

 

좀 추가된 부분이 많습니다.

 

 

 

 

 

그러면 코드를 interface를 이용하여 수정하면 어떻게될까요?

한번 봅시다.

 

interface Barking {
    public void bark();
}

class Cat implements Barking {
    public void bark() {
        System.out.println("Cat sounds 야옹.");
    }
}

class Lion implements Barking {
    public void bark() {
        System.out.println("Lion sounds 어흥.");
    }
}

class Dog implements Barking {
    public void bark() {
        System.out.println("Dog sounds 멍멍.");
    }
}

public class JavaPrac {
    public void barksound(Barking barking) {
        barking.bark();
    }

    public static void main(String args[]) {
        JavaPrac javaprac = new JavaPrac();

        Cat cat = new Cat();
        Lion lion = new Lion();
        Dog dog = new Dog();

        javaprac.barksound(cat);
        javaprac.barksound(lion);
        javaprac.barksound(dog);
    }
}


-- Result
Cat sounds 야옹.
Lion sounds 어흥.
Dog sounds 멍멍.

interface를 사용한 코드입니다.

위 코드에서 핵심적으로 봐야 할 부분은 아래와 같습니다.

public class JavaPrac {
    public void barksound(Barking barking) { // -> 여기가 핵심
        barking.bark();
    }

    public static void main(String args[]) {
        JavaPrac javaprac = new JavaPrac();

        Cat cat = new Cat();
        Lion lion = new Lion();
        Dog dog = new Dog();

        javaprac.barksound(cat);
        javaprac.barksound(lion);
        javaprac.barksound(dog);
    }
}

public class에서 barksound라는 method를 생성했고 이 method는 interface인 Barking을 parameter로 받습니다.

 

그리고 JavaPrac class를 이용하여 javaprac 객체를 만들고,

javaprac 객체에 있는 barksound method를 이용하죠.

그리고 parameter로서 각 동물의 객체를 전달합니다.

 

이것이 왜 중요하냐면

-- method를 만들 때 paramter로서 interface를 받을 수 있다는 것.

-- interface를 parameter로 만들면 interface에 명시된 method를 실행시키는 method를 작성할 수 있다는 것.(barking.bark())

-- 해당 interface를 implement한 class(Cat, Lion, Dog)는 마치 interface가 부모 class, implement된 class가 자식 class처럼 행동하여 interface pararmeter에 전달시킬 수 있다는 것.

 

 

 

그러면 위 코드에 Pig를 추가해봅시다.

interface Barking {
    public void bark();
}

class Cat implements Barking {
    public void bark() {
        System.out.println("Cat sounds 야옹.");
    }
}

class Lion implements Barking {
    public void bark() {
        System.out.println("Lion sounds 어흥.");
    }
}

class Dog implements Barking {
    public void bark() {
        System.out.println("Dog sounds 멍멍.");
    }
}

class Pig implements Barking { // 추가됨
    public void bark() {
        System.out.println("Pig sounds 꿀꿀.");
    }
}

public class JavaPrac {
    public void barksound(Barking barking) {
        barking.bark();
    }

    public static void main(String args[]) {
        JavaPrac javaprac = new JavaPrac();

        Cat cat = new Cat();
        Lion lion = new Lion();
        Dog dog = new Dog();
        Pig pig = new Pig(); // 추가됨

        javaprac.barksound(cat);
        javaprac.barksound(lion);
        javaprac.barksound(dog);
        javaprac.barksound(pig); // 추가됨
    }
}



-- Result
Cat sounds 야옹.
Lion sounds 어흥.
Dog sounds 멍멍.
Pig sounds 꿀꿀.

마찬가지로 추가된 부분에 추가됨이라고 주석 표시를 하였습니다.

어떤가요? 이전에 예시에서 Pig를 추가했을 때에는 Pig관련 class를 생성함과 동시에 어떤 동물의 객체를 받는지에 따라 조건문에도 Pig를 추가해주었는데 여긴 조건문이 필요 없습니다.

 

왜냐면 각 동물의 객체를 받아서 interface의 method(bark())를 실행하고

각 동물 class에는 이미 bark() method에 대해 동물별로 정의가 되어있죠.

즉,

input = 동물 객체

output = interface method

인 것입니다.

 

여러 동물 객체를 input하고

이 동물 객체별 interface method를 실행하도록 하였으니

별도의 조건문이 필요없어진것이죠.

 

 

위 예시로는 이걸 왜 사용해야하는지 잘 모르겠지만

코드가 길어지고 관리해야 할 것들이 늘어나면 위처럼 여러 class(동물 class)들을 단위별로 관리하고

각 class들만 Input시키면 공통된 method를 실행하도록 하는것이 유용합니다.

 

 

이렇게 동일한 method라도 상속받은 자식 class에 따라 다른 결과를 내놓거나 다른 행동을 하도록 하는 것을 polymorphism이라고 합니다.

 

 

 

 

 

 

728x90
반응형

'Java' 카테고리의 다른 글

Java - interface  (0) 2021.03.14
Java - 생성자 (Constructor)  (0) 2021.03.14
Java - class overloading  (0) 2021.03.14
Java - class의 상속  (0) 2021.03.14
Java - ArrayList  (0) 2021.03.13
Comments