[Tistory] 이펙티브 자바 Item 22,23 – 인터페이스는 타입을 정의하는 용도로만 사용하라, 태그 달린 클래스보다는 클래스 계층구조를 활용하라

원글 페이지 : 바로가기

아이템 22 인터페이스는 타입을 정의하는 용도로만 사용하라 메서드 없이 상수 필드만 가득한 상수 인터페이스를 만들지마라. -> 이는 안티 패턴이다. 상수 인터페이스의 구현은 외부 인터페이스가 아닌 내부 구현에 해당하는데, 내부 구현을 외부로 노출할 우려가 있다. 상수를 공개하고 싶다면, 상수 전용 인터페이스를 구현하지 말고 그와 연관된 클래스나 인터페이스에서 공개하도록 하자. 아니면 인스턴스화를 막은 클래스에 담아서 공개하자 상수 공개 방법 1. 클래스나 인터페이스 자체에 상수 추가 방법 [첫 번째 – 클래스, 인터페이스 자체 상수 추가] public final class Integer extends Number implements Comparable {

@Native public static final int MIN_VALUE = 0x80000000;

@Native public static final int MAX_VALUE = 0x7fffffff;

} 2. 열거 타입으로 공개하는 방법 Enum을 사용해서 공개할 수 있다. 3. 유틸리티 클래스에 담아 공개하는 방법 [상수 유틸리티 클래스] public final class StringConstants{
public static final String BLANK = “”;

//인스턴스화를 막은 private 생성자
private StringConstants(){}
} 아이템 23 태그 달린 클래스보다는 클래스 계층구조를 활용하라 여기서 의미하는 태그란 해당 클래스가 어떠한 타입인지에 대한 정보를 담고 있는 필드(멤버 변수)를 의미한다. – 태그로 구분하는 클래스 public class Figure {
enum Shape {RECTANGLE, CIRCLE};

// 태그 필드 – 현재 모양을 나타낸다.
final Shape shape;

// 다음 필드들은 모양이 사각형(RECTANGLE)일 때만 쓰인다.
double length;
double width;

// 다음 필드는 모양이 원(CIRCLE)일 때만 쓰인다.
double radius;

// 원용 생성자
public FigureWithTag(double radius) {
this.shape = Shape.CIRCLE;
this.radius = radius;
}

// 사각형용 생성자
public FigureWithTag(double length, double width) {
this.shape = Shape.RECTANGLE;
this.length = length;
this.width = width;
}

double area() {
switch (shape) {
case RECTANGLE:
return length * width;
case CIRCLE:
return Math.PI * (radius * radius);
default:
throw new AssertionError(shape);
}
}
} 이러한 태그를 가지고 있으면 여러가지 단점이 존재하게 된다. 태그에 대한 선언이 필요하다. 그로 인해 태그 필드를 가지고 있어야한다. 태그에 따른 메서드의 행동이 달라져야 하기 때문에 switch문이 많아진다. 그로 인해 코드를 읽기 힘들어 진다. 만약 필드를 final로 선언한다면 해당 태그에서 사용되지 않는 필드들을 위해 불필요한 초기화가 필요하다. 이러한 부분에서 컴파일러가 도와줄 수 있는 부분이 별로 없다. 결국 태그 달린 클래스는 읽기 어렵기만 하고 오류는 발생하기 쉬우며 비효율적이다. 태그가 달린 클래스의 구현은 클래스의 계층구조를 어설프게 흉내 낸 아류…다! 이를 개선하기 위해 다음과 같은 순서를 밟도록 하자. 1. root가 될 추상 클래스를 정의하자. 2. 태그에 따라 행동이 달라지던 메서드는 추상 메서드로 구현하자 (아니라면 일반 메서드) 3. 공통된 필드는 모드 root 클래스로 올리자 4. root 클래스를 확장한 구체 클래스를 의미별로 정의하자. (각 의미에 해당하는 데이터 필드를 구체 클래스에 정의) 5. 구체 클래스에서 추상 메서드를 의미에 맞게 구현하자. – 상속 구조로 변경 public abstract class Figure {
abstract double area();
}

public class Circle extends Figure {
final double radius;

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

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

public class Rectangle extends Figure {
final double length;
final double width;

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

@Override
double area() {
return length * width;
}
} 참조자료 https://velog.io/@injoon2019/%EC%9D%B4%ED%8E%99%ED%8B%B0%EB%B8%8C-%EC%9E%90%EB%B0%94-%EC%95%84%EC%9D%B4%ED%85%9C-23.-%ED%83%9C%EA%B7%B8-%EB%8B%AC%EB%A6%B0-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%B3%B4%EB%8B%A4%EB%8A%94-%ED%81%B4%EB%9E%98%EC%8A%A4-%EA%B3%84%EC%B8%B5%EA%B5%AC%EC%A1%B0%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EB%9D%BC [이펙티브 자바] 아이템 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 두 가지 이상의 의미를 표현할 수 있으며, 그중 현재 표현하는 의미를 태그값으로 알려주는 클래스다. (사실 본적이 없다). 위의 코드는 원과 사각형을 표현할 수 있다. 열거 타입, 태그 필드, swit velog.io https://javabom.tistory.com/45 [아이템 22, 23] 인터페이스는 타입을 정의하는 용도로만 사용하라, 태그 달린 클래스보다는 클래 아이템 22 인터페이스는 타입을 정의하는 용도로만 사용하라 메서드 없이 상수 필드만 가득한 상수 인터페이스를 만들지마라. 안티 패턴이다. 상수 인터페이스의 구현은 외부 인터페이스가 아 javabom.tistory.com https://velog.io/@alkwen0996/%EC%9D%B4%ED%8E%99%ED%8B%B0%EB%B8%8C-%EC%9E%90%EB%B0%94-%EC%95%84%EC%9D%B4%ED%85%9C22-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%8A%94-%ED%83%80%EC%9E%85%EC%9D%84-%EC%A0%95%EC%9D%98%ED%95%98%EB%8A%94-%EC%9A%A9%EB%8F%84%EB%A1%9C%EB%A7%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%9D%BC [이펙티브 자바] 아이템22 | 인터페이스는 타입을 정의하는 용도로만 사용하라 인터페이스 사용용도 인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다. 달리 말하면 클래스가 어떤 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇 velog.io

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다