본문 바로가기

전체 글

(214)
[아이템 18] 상속보다는 컴포지션을 사용하라 ※ 여기서 말하는 '상속'은 클래스가 다른 클래스를 확장하는 구현 상속을 말한다. 클래스 인터페이스를 구현하거나 인터페이스가 다른 인터페이스를 확장하는 인터페이스 상속과는 무관하다. ※ 상위 클래스와 하위 클래스를 모두 같은 프로그래머가 통제하는 패키지 안에서라면 상속도 안전한 방법이다. 확장할 목적으로 설계되었고 문서화도 잘 된 클래스아이템19도 마찬가지로 안전하다. 하지만, 일반적인 구체 클래스를 패키지 경계를 넘어, 즉 다른 패키지의 구체 클래스를 상속하는 일은 위험하다. [Why] 메서드 호출과 달리 상속은 캡슐화를 깨뜨린다. 상속은 반드시 하위 클래스가 상위 클래스의 '진짜' 하위 타입인 상황에서만 쓰여야 한다. 클래스 A를 상속하는 클래스 B를 작성하려 한다면 "B가 정말 A인가?"라고 자문해..
Code refactoring https://www.jetbrains.com/help/idea/refactoring-source-code.html Code refactoring | IntelliJ IDEA www.jetbrains.com ⌃ T : invoke refactoring(리팩토링 메뉴) ⇧ F6 : Rename(이름 변경) ⌘ ⌦ : Safe Delete(안전한 삭제) F5 / F6 : Copy / Move(복사/이동) ⌥ ⌘ M : Extract Method(메서드 추출) ⌥ ⌘ C : Extract Constant(상수 추출) ⌥ ⌘ F : Extract Field(필드 추출) ⌥ ⌘ P : Extract Parameter(인수 추출) ⌥ ⌘ V : Extract/Introduce Variable(변수 추출/들여오기) ..
[아이템 17] 변경 가능성을 최소화하라 불변 클래스란? 인스턴스의 내부 값을 수정할 수 없는 클래스 불변 인스턴스에 간직된 정보는 고정되어 객체가 파괴되는 순간까지 절대 달라지지 않는다. 자바 플랫폼 라이브러리에서의 예시) String, 기본 타입의 박싱된 클래스들, BigInteger, BigDecimal [Why] 가변 클래스보다 설계하고 구현하고 사용하기 쉽다. 불변 클래스라면 한번 만든 인스턴스를 최대한 재활용할 수 있다. 자주 사용되는 인스턴스를 캐싱하여 중복 생성되지 않게 해주는 정적 팩터리를 제공할 수 있다. 아이템1 불변 객체는 자유롭게 공유할 수 있음은 물론, 불변 객체끼리는 내부 데이터를 공유할 수 있다. 객체를 만들 때 다른 불변 객체들을 구성요소로 사용하면 그 구조가 아무리 복잡하더라도 불변식을 유지하기 수월하다. 오류가..
[아이템 16] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 [Why] class Point { public double x; public double y; } 인스턴스 필드를 모아놓는 일 외에는 아무 목적도 없는 퇴보한 클래스 데이터 필드에 직접 접근할 수 있으니 캡슐화의 이점을 제공하지 못한다. 아이템15 API를 수정하지 않고는 내부 표현을 바꿀 수 없고, 불변식을 보장할 수 없으며, 필드에 접근할 때 부수 작업을 수행할 수도 없다. [When] public 클래스에서라면 접근자를 제공함으로써 클래스 내부 표현 방식을 언제든 바꿀 수 있게 한다. package-private 클래스 혹은 private 중첩 클래스라면 데이터 필드를 노출한다 해도 하등의 문제가 없다. [How] public 클래스 class Point { private double x; pri..
[아이템 15] 클래스와 멤버의 접근 권한을 최소화하라 ※ 어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 바로 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐다. 정보은닉, 혹은 캡슐화라고 하는 이 개념은 소프트웨어 설계의 근간이 되는 원리다. ※ 멤버(필드, 메서드, 중첩 클래스, 중첩 인터페이스)에 부여할 수 있는 접근 수준은 네 가지다. · private: 멤버를 선언한 톱레벨 클래스에서만 접근할 수 있다. · package-private: 멤버가 소속된 패키지 안의 모든 클래스에서 접근할 수 있다. 접근 제한자를 명시하지 않았을 때 적용되는 패키지 접근 수준이다. (단, 인터페이스의 멤버는 기본적으로 public이 적용된다) · protected: package-private의 접근 범위를 포함하며, 이..
[아이템 14] Comparable을 구현할지 고려하라 ※ compareTo는 Object의 메서드가 아니다. (equals, hashCode, toString, clone은 Object의 메서드) ※ compareTo 메서드 : 객체가 주어진 객체보다 작으면 음의 정수를, 같으면 0을, 크면 양의 정수를 반환한다. 객체와 비교할 수 없는 객체가 주어지면 ClassCastException을 던진다. [Why] compareTo는 단순 동치성 비교에 더해 순서까지 비교할 수 있으며, 제네릭하다. Comparable을 구현한 객체들의 배열은 손쉽게 정렬할 수 있다. e.g.) Arrays.sort(a); [When] 알파벳, 숫자, 연대 같이 순서가 명확한 값 클래스를 작성한다면 반드시 Comparable 인터페이스를 구현하자. [How] equals 규약과 똑..
[아이템 13] clone 재정의는 주의해서 진행하라 ※ Cloneable 인터페이스에 대하여 더보기 복제해도 되는 클래스임을 명시하는 용도의 mixin interface아이템20. 메서드 하나 없는 Cloneable 인터페이스는 Object의 protected 메서드인 clone의 동작 방식을 결정한다. 가장 큰 문제는 clone 메서드가 선언된 곳이 Cloneable이 아닌 Object라는 점과 protected로 선언되어있다는 점이다. Cloneable은 상위 클래스에 정의된 protected 메서드의 동작 방식을 변경한 것이다. (따라하지 말자!) 그래서 Cloneable을 구현하는 것만으로는 외부 객체에서 clone 메서드를 호출할 수 없다. Cloneable을 구현한 클래스의 인스턴스에서 clone을 호출하면 그 객체의 필드들을 하나하나 복사한 ..
[아이템 12] toString을 항상 재정의하라 [Why] toString의 일반 규약에 따르면 '간결하면서 사람이 읽기 쉬운 형태의 유익한 정보'를 반환해야 한다. toString의 규약은 '모든 하위 클래스에서 이 메서드를 재정의하라'고 한다. [When] 모든 구체 클래스에서 Object의 toString을 재정의하자. 상위 클래스에서 이미 알맞게 재정의한 경우는 예외다. toString 메서드는 객체를 println, printf, 문자열 연결 연산자(+), assert 구문에 넘길 때, 혹은 디버거가 객체를 출력할 때 자동으로 불린다. toString을 제대로 정의하지 않는다면 쓸모없는 메시지(클래스_이름@16진수로_표시한_해시코드)만 로그에 남을 것이다. 정적 유틸리티 클래스는 toString을 제공할 이유가 없다. 대부분의 열거 타입아이템..