본문 바로가기
Java

Java 기본 - 다형성 1

by KongJiHoon 2025. 1. 22.

** 다형성(Polymorphism) : 객체지향 프로그래밍에서 하나의 객체가 여러가지 타입을 가질 수 있는 성질(다형성의 핵심은 다형적 참조와 메서드 오버라이딩이다.)

 

예제 코드

 

Animal

package poly.ex2;

public class Animal {


    public void sound() {
        System.out.println("동물 울음 소리");
    }

}

 

Dog

package poly.ex2;

public class Dog extends Animal{

    @Override
    public void sound() {
        System.out.println("멍멍");
    }
}

 

Cat

package poly.ex2;

public class Cat extends Animal{

    @Override
    public void sound() {
        System.out.println("냐옹");
    }
}

 

 

package poly.ex2;

public class AnimalSoundMain2 {

    public static void main(String[] args) {

        Animal[] animals = {new Cat(), new Dog(), new Cow()};

        for (Animal animal: animals) {
            soundAnimal(animal);
        }
    }

    private static void soundAnimal(Animal animal) {
        System.out.println("동물 움음 소리 테스트 시작");
        animal.sound();
        System.out.println("동물 울름 소리 테스트 종료");
    }
}

 

 

  • soundAnimal(Animal animal)을 호출하면 animal을 상속받고 있는 인스턴스가 전달이 된다. 그 다음 메서드가 실행되는데, 이 때 원래는 부모객체의 sound()가 호출 되어야 하지만 자식 객체의 메서드가 호출이 된다. 메서드 오버라이딩은 오버라이딩한 메서드가 우선권을 가진다.
  • 다형적 참조 덕분에 animal 변수는 자식인 Dog, Cat, Cow의 인스턴스를 참조할 수 있다.
  • 메서드 오버라이딩 덕분에 animal.sound()를 호출해도 Dog.sound(), 등 자식 객체의 메서드를 호출 할 수 있었다.

 

추상 클래스

  • Animal과 같이 부모 클래스는 제공하지만, 실제 생성되면 안되는 클래스를 추상 클래스라 한다. 추상클래스는 이름 그대로 추상적인 개념을 제공하는 클래스. 따라서 실체인 인스턴스가 존재하지 않는다. 대신에 상속을 목적으로 사용되고, 부모 클래스 역할을 한다.
  • 추상클래스는 선언할 때 앞에 abstract라는 키워드를 붙여주면된다.
  • 추상 메서드가 하나라도 있는 클래스는 추상 클래스로 선언해야 한다.
  • 추상 메서드는 메서드 바디가 없다.
  • 추상 메서드는 상속받는 자식 클래스가 반드시 오버라이딩하여 사용

예제코드

 

AbstractAnimal

package poly.ex4;

public abstract class AbstractAnimal {

    public abstract void sound();

    public abstract void move();
}

 

 

Dog

package poly.ex4;

public class Dog extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("멍멍");
    }

    @Override
    public void move() {
        System.out.println("개이동");
    }
}

 

Cat

package poly.ex4;

public class Cat extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("냐옹");
    }

    @Override
    public void move() {
        System.out.println("고양이 이동");
    }
}

 

Cow

package poly.ex4;

public class Cow extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("음메");
    }

    @Override
    public void move() {
        System.out.println("소이동");
    }
}

 

package poly.ex4;

public class AbstractAnimalSoundMain {

    public static void main(String[] args) {
        AbstractAnimal animal1 = new Dog();
        AbstractAnimal animal2 = new Cat();
        AbstractAnimal animal3 = new Cow();

        AbstractAnimal[] animals = {animal1, animal2, animal3};

        for (AbstractAnimal animal : animals) {
            soundAnimal(animal);
            moveAnimal(animal);
        }
    }

    private static void soundAnimal(AbstractAnimal animal) {
        System.out.println("동물 울음소리 테스트 시작");
        animal.sound();
        System.out.println("동물 울음소리 테스트 종료");

    }

    private static void moveAnimal(AbstractAnimal animal) {
        System.out.println("동물 이동 테스트 시작");
        animal.move();
        System.out.println("동물 이동 테스트 종료");

    }
}

 

실행결과

동물 울음소리 테스트 시작
멍멍
동물 울음소리 테스트 종료
동물 이동 테스트 시작
개이동
동물 이동 테스트 종료
동물 울음소리 테스트 시작
냐옹
동물 울음소리 테스트 종료
동물 이동 테스트 시작
고양이 이동
동물 이동 테스트 종료
동물 울음소리 테스트 시작
음메
동물 울음소리 테스트 종료
동물 이동 테스트 시작
소이동
동물 이동 테스트 종료

 

  • 위 AbstractAnimal의 추상 메서드처럼 추상 클래스의 메서드는 로직을 가지지 않는다.
  • 또한 상속받는 자식 클래스는 부모 클래스의 모든 추상메서드를 오버라이딩 해야 한다.

 

인터페이스

** 자바는 순수 추상 클래스를 더 편리하게 사용할 수 있는 인터페이스라는 기능을 제공.

  • 인터페이스는 추상 클래스와 같다. 여기에 약간의 편의 기능이 추가된다.
    • 인터페이스의 메서드는 모두 public, abstract이다.
    • 생략 권장
    • 인터페이스는 다중 구현(다중 상속)을 지원
    • 자바는 다중 상속을 지원하지 않는다. 부모는 단 하나

예제 코드

InterfaceA

package poly.diamond;

public interface InterfaceA {

    void methodA();

    void methodCommon();
}

 

InterfaceB

package poly.diamond;

public interface InterfaceB {

    void methodB();

    void methodCommon();
}

 

Child

package poly.diamond;

public class Child implements InterfaceA, InterfaceB{
    @Override
    public void methodA() {
        System.out.println("Child.methodA");
    }

    @Override
    public void methodB() {
        System.out.println("Child.methodB");
    }

    @Override
    public void methodCommon() {
        System.out.println("Child.methodCommon");
    }
}

 

DiamondMain

 

package poly.diamond;

public class DiamondMain {

    public static void main(String[] args) {


        InterfaceA a = new Child();
        a.methodA();
        a.methodCommon();
        InterfaceB b = new Child();

        b.methodB();
        b.methodCommon();
    }
}

 

실행결과

Child.methodA
Child.methodCommon
Child.methodB
Child.methodCommon
  • 위 코드와 같이 interface 키워드를 사용하고, 구현할 시에는 implement를 사용한다.
  • 위 Child 객체는 InterfaceA와 InterfaceB를 다중 상속을 받고 있다. 그래서 Child에서 오버라이딩 해주었고, 참조영역에는 InterfaceA, InterfaceB 둘다 주어진다.

 

**다형성은 이렇게 추상클래스 인터페이스를 사용하여 다형적 참조와 메서드 오버라이딩을 활용한다.

'Java' 카테고리의 다른 글

JAVA 중급 1 - Object 클래스  (0) 2025.02.14
Java 기본 - 다형성과 설계  (0) 2025.01.30
Java 기본 - 상속  (0) 2025.01.03
Java 기본 - final  (0) 2025.01.02
Java 기본 - 자바 메모리 구조 및 static  (1) 2024.12.25