전체 글
클래스와 인터페이스 - 규칙 19 인터페이스는 자료형을 정의할 때만 사용하라.
인터페이스를 구현하는 클래스를 만들경우, 그 인터페이스는 해당 클래스의 객체를 참조할 수 있는 자료형 역할을 하게 된다. 상수 인터페이스 => 메서드가 없고 static final 필드만 있어, 상수 이름 앞에 클래스 이름을 붙이는 번거로움을 피하기 위해서이다. 123public interface PhysicalConstants { static final double AVOGADROS_NUMBER = 6.02312312323;}Colored by Color Scriptercs 이런 상수 인터페이스 패턴은 인터페이스를 잘못 사용한 것이다. => 인터페이스는 사용자에게 이러한 기능을 구현한 클래스라는 명세를 알려주는거와 같은데 상수 인터페이스는 기능 명세를 제공하는 것이 아니라 상수값을 사용하기 위한 것으로..
클래스와 인터페이스 - 규칙 18 추상 클래스 대신 인터페이스를 사용하라.
자바는 다중 상속이 되지 않기 때문에, 추상 클래스 보다 인터페이스를 사용하는 것이 좋다. 믹스인 인터페이스는 믹스인을 정의하는 데 이상적이다. => 믹스인은 클래스가 주 자료형 이외에 추가로 구현할 수 있는 자료형으로 어떤 선택적 기능을 제공한다는 사실을 선언하기 위해 쓰인다. => 예를 들면, Comparable은 어떤 클래스가 자기 객체를 다른 객체와의 비교 결과에 따른 순서를 갖는다고 선언할 때 쓰는 인터페이스이다. 이런 믹스인 기능을 추상클래스에 할 수 없다. => 클래스가 가질 수 있는 상위 클래스는 하나 이기 때문에 좋은 방법이 아니다. 인터페이스는 여러 속성을 합쳐서 새로운 속성을 만들 수 있다. => singer와 SongWriter 속성을 합쳐서 새로운 인터페이스를 만들 수 있다. 12..
클래스와 인터페이스 - 규칙 17 계승을 위한 설계와 문서를 갖추거나, 그럴 수 없다면 계승을 금지하라.
16번에서 정의한 것처럼 계승 (이하 상속)을 받을 경우 문제를 야기할 수 있다. 그렇기에 이를 예방하기 위해서 문서를 잘 갖추고 있어야 하는데 문서를 갖춘다는 것은 어떤 의미일까? 이는 재정의 가능 메서드를 내부적으로 어떻게 사용하는지(self-use)반드시 남기라는 것이다. -> 어떤 재정의 가능 메서드를 어떤 순서로 호출하는지, 그리고 호출결과가 추후 어떤 영향을 미치는지 문서로 남기라는 의미이다. 여러 문제를 야기할 수 있기에, 계승에 맞도록 설계하고 문서화하지 않은 클래스에 대한 하위 클래스는 만들지 않아야 한다. 출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙17 인용.
클래스와 인터페이스 - 규칙 16 계승하는 대신 구성하라.
상속은 코드를 재사용 할 수 있도록 돕는 강력한 도구이지만, 항상 최선이라 할 수 없다. 제대로 구현하지 못한 경우 문제를 유발할 가능성이 크기 때문이다. 그리고 같은 패키지 내부에 존재하는 클래스를 상속받아야한다. 상속은 일반적으로 캡슐화 원칙을 위반한다. 그 이유는 상위클래스의 일부 개념이 변경될 경우, 하위클래스는 그대로 영향을 받을 수 밖에 없기 때문이다. 이를 예방하기 위해서는 문서를 제대로 구현해 놓아야 한다. 문제가 야기될 수 있는 상황은 다음과 같다. 1. 기존의 재정의 하여 사용하였을 경우. -> 문제가 될 수 있는 상황을 예를 들면, HashSet을 상속하고 add관련 메서드를 재정의하여 객체를 추가한 횟수를 확인하는 로직을 추가하는 로직을 만들어보자 1234567891011121314..
클래스와 인터페이스 - 규칙 15 변경 가능성을 최소화하라
immutable 클래스는 그 객체를 수정할 수 없는 클래스이다. 객체 내부의 정보는 객체가 생성될 때 주어진 것이며, 객체가 살아 있는 동안 그대로 보존된다. 이러한 변경 불가능 클래스를 만드는 이유는 다양하다. - 설계가 쉽다. - 오류 가능성이 적고 안전하다. 생성 규칙 - 객체 상태를 변경하는 메서드를 제공하지 않는다. (setter) - 상속할 수 없도록 진행한다. => 하위 클래스가 객체 상태가 변경된 것처럼 동작할 수 있다. => class에 final을 붙힌다. - 모든 필드를 final로 생성한다. => 이렇게 생성할 경우 생성된 객체에 대한 참조가 동기화(Synchronization)없이 다른 스레드로 전달 되어도 안전하다. - 모든 필드를 private로 선언한다. => 모든 필드를 ..
클래스와 인터페이스 - 규칙 14 public 클래스 안에는 public 필드를 두지 말고 접근자 메서드를 사용하라
가끔 아래 기재된 클래스 처럼 클래스 내부에서 사용할 데이터를 처리하기 위해 임시 클래스를 만드는 경우가 있다. 1234class Temp { private String t; private String f;} cs 이런 경우에는 이 클래스를 직접 조작할 수 있기 때문에 캡슐화의 이점이 사라질 수 밖에 없다. 하지만 package-private 클래스나 private 중첩 클래스는 데이터의 필드가 공개되더라도 잘못이라 말할 수 없다. 대신 클래스가 추상화 하려는 내용을 제대로 기술하기만 하면 된다. 기존의 public 클래스가 내부 필드를 외부로 공개하는 것은 바람직하지 않지만, 변경 불가능 필드는 그 심각성이 덜하다. 다음과 같이 내부 변수를 public으로 공개하여도 어떤한 동작도 하지 못하게(immu..
클래스와 인터페이스 - 규칙 13 클래스와 멤버의 접근권한은 최소화하라.
잘 설계된 모듈과 그렇지 못한 모듈을 구분 짓는 가장 중요한 속성은 바로 구현된 세부사항을 얼마나 잘 감추었는지를 통해 확인할 수 있다. 정보은닉을 통해 서로 API를 통해서만 이용하며, 뒤에서 동작 방식은 상관하지 않기 때문에 의존성이 낮아져 병렬적으로 개발할 수 있기 때문에 유지보수의 부담감과 다른 모듈에 영향을 끼치는 부분이 줄어들게 된다. 자바의 정보은닉 원칙은 단순하다. 각 클래스와 멤버는 가능한 한 접근 불가능하도록 만드는 것. Public을 부여하는 경우에는 전역적 객체가 되고, 아무런 접근 권한을 부여하지 않으면 package-private로 내부 패키지 접근만 가능하다. 자세한 접근 권한 규칙은 다음과 같다 Private : 클래스 내부에서만 접근이 가능하다. Package-private..
모든 객체의 공통 메서드 - 규칙 12 Comparable 구현을 고려하라.
CompareTo 메서드는 Object에 선언되어 있지 않으며, Comparable 인터페이스에 포함된 유일한 메서드이다. Object의 equals 메서드와 비슷한 특성을 가지고 있으나, 동치성 검사를 넘어 순서 비교도 가능하다. Comparable 인터페이스를 구현한 객체들은 검색하거나, 정렬, 최대/최소 구하기 등이 간단하며 정렬도 다음과 같이 간단하게 진행 할 수 있다. Arrays.sort(a) 그렇기에 알파벳 순서나 값의 크기, 또는 시간적 선후 관계처럼 명확한 자연적 순서를 가지는 값을 가진 클래스를 구현할 때는 Comparable 인터페이스를 구현하는 것이 좋다. 1234Public interface Comparable { int compareTo(T t);} Colored by Color..
모든 객체의 공통 메서드 - 규칙 11 clone을 재정의할 때는 신중하라
Cloneable은 객체의 복제를 허용한다는 사실을 알리는데 쓰려고 고안된 인터페이스이다. 하지만 Cloneable은 선언된 메서드가 없는 마커 인터페이스로, 상위 클래스의 protected 멤버가 어떻게 동작할지 규정하는 용도로 쓰인다. 또한 객체의 cloneable을 구현하면, Object의 clone 메서드는 해당 객체를 필드 단위로 복사한 객체를 반환한다. Cloneable을 구현하지 않았다면, clone 메서드는 CloneNotSupportedException을 던질 것이다. Java API 문서에 기재된 clone 메서드의 명세는 다음과 같다. - 객체의 복사본을 만들어서 반환한다. - "복사"의 정확한 의미는 클래스마다 다르다. - 일반적으로 x.clone() != x 는 참이다. - x.c..
모든 객체의 공통 메서드 - 규칙 10 toString은 항상 재정의하라
toString 재정의를 하지 않은 경우 기본으로 제공되는 toString을 사용하게 될 경우 @ 기호와 16진수로 표현된 해시코드가 붙은 문자열이 반환된다. 이는 사용자가 원하는 정보가 아니므로 사용자는 해당 객체가 원하는 형태로 문자열을 반환할 수 있도록 재정의를 해놓으면 조금 더 유용하게 사용 할 수 있다. 일반적으로 toString 메서드를 재 정의하여 사용하는 경우에는 객체 내의 중요 정보를 전부 담아 반환해야 한다. 또한 toString를 재정의 하였을 경우에는 해당 내용에 대한 주석을 상세하게 기입해 놓아야 한다. 12345678910/* * 모든 객체의 멤버 변수에 대한 데이터를 반환한다. * * a는 첫번재, b는 두번 째 값이다. */ @Override public String toSt..