[F-lab 모각코 챌린지 21일차] TIL

JeongheeKim·2023년 6월 21일

TIL

목록 보기
21/66

공부하면서 사용한 예제에 대해 아래와 같은 질문을 받았다. 질문에 대해 다시 정리해보고자 한다.

위 상속 예시를 보면 area라는 상태를 부모클래스에서 관리하고 있습니다. 과연 상속관계에서 area라는 상태가 필요할까요? 상태가 필요하지 않다면 인터페이스로 분리할 수 있지 않을까요?

public abstract class Shape {
    private double area;
    public abstract double getArea();
}
public class Circle extends Shape {
    double radius;

    public Circle( double r ) {
        radius = r;
    }

    public double getArea() {
        area = 3.14 * ( radius * radius );
        return ( area );
    }
}
public class Rectangle extends Shape{
    double length;
    double width;

    public Rectangle( double l, double w ) {
        length = l;
        width = w;
    }

    public double getArea() {
        area = length * width;
        return ( area );
    }
}

질문에 대해 나의 대답은 이러했다.
공통 속성이라고 생각했고, 예제에 검증도 부족했다.
또한 인터페이스는 필드 선언이 불가하다는 개념적 오류도 가지고 있었다. (상수 선언 가능)

→ 부모클래스에 area(면적) 필드를 추가한것은 하위객체들이 동일한 속성에 대한 값을 정의하기 위해 필요하다고 생각합니다. 자식 클래스에서 area에 대한 필드를 선언하면 코드 중복이 발생하거나 필드 타입이 동일하게 유지 되지 않을 수 있습니다.

인터페이스로 분리하면 area에 대한 필드 선언이 불가하여 부모클래스로 선언하는것이 적절하다고 생각합니다. 인터페이스를 사용하는 용도로는 메소드(기능)에 대한 명세를 구현 클래스마다 동일하게 약속하기 위함이기 때문입니다.


예제가 가지는 문제점에 대해 살펴보자.

문제점

  1. area필드의 필요성

Shape이라는 추상클래스의 area필드를 선언하여 하위 도형클래스에 상속하였다. area란 도형들의 상태에 따라 값이 계산되어 변경되는 멤버변수 이다. 상속 시 사용할 필드(속성)에 적합하지 않다. 상태를 나타낼 필드가 없애면 인터페이스로 도형의 공통된 기능을 정의할 수 있다.

  1. private로 선언된 area 필드

    위의 코드에서 하위 상속받은 getArea에서 접근이 불가하다.

  2. getter 메소드의 역할 명확하지 않음

    getArea메소드에 단일책임원칙에 위반되어 set과 get의 기능 두가지를 하고 있다.

해결방안

  1. area필드를 제거하고 interface로 공통 메소드 정의
  2. area에 대한 필드에 담는것이 아닌 getter메소드에서 정의 및 메소드 단일 책임원칙 적용

해결방법을 적용하면 아래와 같이 예제 코드를 고칠 수 있다.

public interface Shape {
	 double getArea();
}
public class Circle implements Shape {
	double radius;

	public Circle( double r ) {
		radius = r;
	}

	public double getArea() {
		return 3.14 * ( radius * radius );
	}
}
public class Rectangle implements Shape {
	double length;
	double width;

	public Rectangle( double l, double w ) {
		length = l;
		width = w;
	}

	public double getArea() {
		return length * width;
	}
}

SRP : 단일 책임 원칙 (Single Resposibility Priciple)
하나의 클래스는 하나의 책임을 가진다
하지만 하나의 책임의 기준이 애매함

⇒ 변경이 있을 때 파급효과가 적으면 단일 책임 원칙을 잘 따르는 것

LSP: 리스코프 치환 원칙(Liskov substitution Priciple)
인터페이스에서 정의한 기능을 무조건 따라야 함
예)자동차 인터페이스 악셀기능은 앞으로 간다는 기능으로 정의됨
car interface를 구현한 테슬라 구현체가 엑셀 메서드 실행 시 뒤로가면 리스코프 치환 원칙을 위배하게됨

0개의 댓글