상속과 컴포지션

eomprgrm·2023년 3월 5일
0

이펙티브자바

목록 보기
2/3

이펙티브 자바를 읽던 중 item 18의 주제인 '상속보다는 컴포지션을 사용하라' 의 내용이 머릿속에 쉽게 그려지지 않았다. 따라서 해당 내용에 대해 간략하게 정리를 해보려고 한다.
(이해 안 되면 일단 외우기)

상속 : is-a 관계 (하위 클래스가 상위 클래스의 특성을 재정의 할 수 있는)
컴포지션 : has-a 관계 (기존 클래스가 새로운 클래스의 멤버가 될 수 있는)

상속을 사용하는 예제코드이다.

public class Rectangle {
    protected int width;
    protected int height;

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getArea() {
        return width * height;
    }
}

public class Square extends Rectangle {
    
    @Override
    public void setWidth(int width) {
        this.width = width;
        this.height = width;
    }
    
    @Override
    public void setHeight(int height) {
        this.width = height;
        this.height = height;
    }
}

다음과 같은 직사각형 Rectangle 클래스를 상속받은 정사각형 Square 클래스가 있다.
Square 클래스는 Rectangle 클래스의 setWidth(), setHeight() 메서드를 오버라이딩 하고 있는데
정사각형은 높이와 넓이가 같이 때문에 논리적으로 합당한 구현이지만 상위 클래스인
직사각형 Rectangle 클래스의 일반적인 기능과 다르기 때문에 이러한 구현 방식은 코드를 이해하기 어렵게 만들고 따라서 유지보수에 문제를 겪게 된다.

다음과 같은 형태인 상속의 문제점
1. 클래스의 복잡도가 증가한다.
2. 캡슐화를 저해한다.
3. 상위타입의 구현이 변경될 경우 하위타입을 사용할 때,
의도하지 않은 문제가 생길 수 있다.

이러한 문제를 개선하기 위해 컴포지션을 사용한 예제코드이다.

public class Rectangle {
    private int width;
    private int height;

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

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public int getArea() {
        return width * height;
    }
}

public class Square {
    private Rectangle rectangle;

    public Square(int side) {
        this.rectangle = new Rectangle(side, side);
    }

    public int getSide() {
        return rectangle.getWidth();
//        return rectangle.getHeight();
    }

Square 클래스는 Rectangle 클래스를 상속받은 대신, 객체의 멤버로 구현하였다.
이렇게 구현함으로써 Rectangle 클래스의 특성을 가질 수 있고,
또한 독립적으로 존재하기 때문에 더욱 유연한 설계가 가능하다.

profile
오늘의 학습을 기록하는 공간

0개의 댓글