나를 기록하다
article thumbnail
Published 2023. 4. 5. 22:27
[Java] 다형성(polymorphism) Java
반응형

다형성을 사용하는 이유는?

자바에서 다형성을 사용하는 주된 이유는

코드의 재사용성과 확장성

을 높이기 위해서입니다. 다형성을 사용하면, 상위 클래스나 인터페이스를 이용해 여러 하위 클래스들을 참조할 수 있기 때문에,

코드의 일부분만 변경하거나 추가함으로써 쉽게 기능을 확장

할 수 있습니다.

조상 타입의 참조 변수를 사용하는 것이 인스턴스의 일부 멤버만 사용할 수 있다고 느낄 수도 있지만, 실제로는 상속받은 클래스 간에 공통적인 기능을 사용하는 것이 중요합니다. 이렇게 함으로써

다른 클래스들과의 결합도를 낮추고, 유지보수와 확장에 용이한 코드를 작성

할 수 있습니다.

예를 들어, 동물의 특징을 모델링하는 상위 클래스인 Animal이 있고, 이를 상속받는 Dog, Cat, Bird 등의 하위 클래스가 있다고 가정해 봅시다. 이 경우, 다형성을 사용하면 Animal 타입의 참조 변수를 사용하여 Dog, Cat, Bird 등의 인스턴스를 가리킬 수 있습니다. 이렇게 하면 각 동물의 종류에 따라 다르게 구현된 메소드를 호출할 수 있으며, 새로운 동물의 종류를 추가하거나 변경할 때 코드의 다른 부분을 수정할 필요가 없습니다.

결론적으로, 다형성은 자바에서 코드의 재사용성과 확장성을 높이는 중요한 개념입니다. 조상 타입의 참조 변수를 사용하면서 일부 멤버만 사용할 수 있다고 생각할 수 있지만, 이는 공통된 기능을 활용하고 유연한 코드를 작성하기 위한 기본 원칙입니다.

 

 

조상 타입으로 형변환할 때의 장점

  1. 코드의 유연성: 조상 타입의 참조 변수를 사용하면, 다양한 자손 타입들을 통합하여 처리할 수 있습니다. 이를 통해 코드의 유연성이 향상되며, 다양한 타입의 객체를 동일한 방식으로 처리하는 로직을 작성할 수 있습니다.
  1. 다형성 구현: 조상 타입으로 형변환을 통해 다형성을 구현할 수 있습니다. 이를 통해 메소드 오버라이딩을 활용하여 자손 클래스의 인스턴스가 조상 클래스의 메소드를 대체하여 실행되도록 할 수 있습니다. 이러한 방식은 유지 보수와 확장성에 이점을 제공합니다.
  1. 인터페이스 활용: 인터페이스를 구현한 클래스들을 인터페이스 타입으로 형변환하여 사용하면, 서로 다른 클래스들이 공통된 기능을 구현할 수 있습니다. 이를 통해 유연한 코드 설계와 기능 확장이 가능해집니다.
  1. 메소드 매개변수: 조상 타입을 메소드의 매개변수로 사용하면, 다양한 자손 타입의 객체를 인수로 전달받을 수 있습니다. 이를 통해 메소드를 보다 일반화시키고, 다양한 객체를 처리하는 로직을 작성할 수 있습니다.

단점으로는,

조상 타입으로 형변환된 참조 변수로는 자손 타입의 멤버에 직접 접근할 수 없다는 점

이 있습니다. 이 경우, 다시 자손 타입으로 형변환을 해야 자손 클래스의 멤버를 사용할 수 있습니다. 그러나 이러한 단점도 적절한 설계를 통해 극복할 수 있습니다.

 

 

다형성 활용 예시

예를 들어, 도형을 나타내는 상위 클래스 Shape가 있고, 이를 상속받는 Circle, Rectangle, Triangle 등의 하위 클래스들이 있다고 가정해 봅시다. 이 때, 각 도형마다 넓이를 구하는 calculateArea() 메소드를 구현하려고 합니다.

 

 

먼저, 상위 클래스 Shape를 선언하고, calculateArea() 메소드를 추상 메소드로 선언합니다.

abstract class Shape {
    abstract double calculateArea();
}

 

 

그 다음, Shape를 상속받는 Circle, Rectangle, Triangle 클래스를 정의하고, 각 클래스에 맞게 calculateArea() 메소드를 오버라이딩하여 구현합니다.

class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    double calculateArea() {
        return Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    double calculateArea() {
        return width * height;
    }
}

class Triangle extends Shape {
    private double base;
    private double height;

    public Triangle(double base, double height) {
        this.base = base;
        this.height = height;
    }

    @Override
    double calculateArea() {
        return 0.5 * base * height;
    }
}

 

 

이제 조상 타입으로 형변환을 사용하여 코드의 유연성을 살펴보겠습니다.

다양한 도형들의 넓이를 구하는 메소드를 작성해 보겠습니다.

public static void printArea(Shape shape) {
    System.out.println("도형의 넓이: " + shape.calculateArea());
}

위의 printArea() 메소드는 Shape 타입의 매개변수를 받아서 해당 도형의 넓이를 출력합니다. 이 메소드는 Shape 클래스를 상속받은 어떤 도형 객체도 처리할 수 있습니다.

다음은 메인 메소드에서 이를 사용하는 예입니다.

public static void main(String[] args) {
    Circle circle = new Circle(5);
    Rectangle rectangle = new Rectangle(4, 6);
    Triangle triangle = new Triangle(3, 7);

    printArea(circle);
    printArea(rectangle);
    printArea(triangle);
}

위의 예시에서, printArea() 메소드는 Shape 타입의 매개변수를 받기 때문에, Circle, Rectangle, Triangle 객체를 모두 처리할 수 있습니다. 만약 나중에 새로운 도형 클래스를 추가하더라도, printArea() 메소드를 수정할 필요 없이 동일하게 활용할 수 있습니다. 이렇게 조상 타입으로 형변환을 사용하면, 코드의 유연성과 확장성이 향상되며, 다양한 자손 타입을 동일한 방식으로 처리할 수 있습니다.

또한, 도형 배열을 생성하여 각 도형의 넓이를 한 번에 출력할 수도 있습니다. 이를 통해 조상 타입으로 형변환의 장점을 확인할 수 있습니다.

 

 

public static void main(String[] args) {
    Shape[] shapes = new Shape[3];
    shapes[0] = new Circle(5);
    shapes[1] = new Rectangle(4, 6);
    shapes[2] = new Triangle(3, 7);

    for (Shape shape : shapes) {
        printArea(shape);
    }
}

위의 예시에서, Shape 타입의 배열에 각각의 도형 객체를 저장할 수 있습니다. 이렇게 하면, for 문을 사용하여 도형 배열을 순회하면서 각 도형의 넓이를 출력할 수 있습니다. 여기서도 다형성을 활용하여 다양한 도형 객체를 처리할 수 있습니다.

결론적으로, 조상 타입으로 형변환을 사용하면 다양한 자손 클래스의 객체를 동일한 방식으로 처리할 수 있습니다. 이를 통해 코드의 유연성과 확장성이 향상되며, 다형성을 구현할 수 있습니다. 이러한 방식은 객체 지향 프로그래밍에서 중요한 설계 원칙 중 하나로 간주되며, 실제 프로젝트에서도 많이 활용되고 있습니다.

반응형
profile

나를 기록하다

@prao

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...