클래스의 객체의 생성을 막을 수 있는 방법은 두가지가 있다.
하나는 클래스를 추상 클래스 (abstract class) 로 만드는 것이고 다른 하나는 생성자를 private 으로 만드는 것이다.
그전에 왜 객체 생성을 막는 클래스를 만들어야 하는지 생각해봐야 할 것 같다.
객체 생성을 막으면 객체 지향적으로 개발을 할 수가 없다. 객체 지향적 언어를 절차적으로 사용할 수 밖에 없게 된다.
그러나 이런 클래스도 필요 할 경우가 있다. 다음의 세가지 경우가 이에 해당한다.
* 객체 생성을 막아야 할 경우 = 유틸리티 클래스
1. 자바의 기본 자료형 또는 배열에 적용되는 메서드를 한군데 모아둘때 (java.lang.Math, java.util.Array)
2. 특정 인터페이스를 구현하는 객체를 만드는 팩터리 메서드 (java.util.Collections)
3. final 클래스에 적용할 메서드들을 모아 놓을때 (잘 이해가 안간다.)
- final 클래스는 상속을 불가능하게 만든다.
- 상속이 불가능하다는 것은 하위 클래스가 없다는 것이고 하위 클래스에서 메서드를 추가할 수도 없다.
- 따라서 final 클래스는 api 클래스를 만들때 주로 사용한다.
api클래스를 final 로 만들면 최종 사용자가 api 클래스를 상속하여 변형하는 것을 막을 수 있다.
이제 왜 객체 생성을 막는 방법을 알아야 하는지 이해가 갈 것이다.
주제로 다시 돌아와서 객체생성을 막는 방법을 알아보자
1. 추상 클래스
추상 클래스 자체로 보자면 객체 생성은 막을 수 있다.
다만 추상 클래스는 다른 어떤 하위 클래스에서 상속 할 때 추상 클래스의 특성을 가진 하위 클래스가 되고
그 하위 클래스는 객체 생성이 가능하다.
추상 클래스는 하위 클래스들을 추상화 한 것으로 원래 목적을 고려 하면 추상 클래스 선언으로 객체 생성을
막는 시도는 잘못된 생각이다.
2. 생성자를 private 로 선언
public class UtilityClass {
/**
* 선언된 생성자가 없을때 기본생성자가 생성되기 때문에
* 기본 생성자가 자동 생성되지 못하도록 하여 객체 생성 방지
*
* private 선언으로 외부에서 접근 하지 못하도록
* reflection 으로 생성자를 실행 시키는 것을 방지하고
* 클래스 안에서 실수로 생성자를 호출하면 바로 알 수 있게 하기 위해
* Exception 을 throw 하도록 구현
*
*/
private UtilityClass() {
throw new AssertionError();
}
}
코드의 주석을 통해 private 으로 생성자를 만들어 객체를 생성 불가능하게 만드는 방법을 설명했다.
이 방법은 하위 클래스를 만들 수 없게 하기 때문에 abstrace class 와는 다게게 상속을 통해 객체를 생성하지 못하도록 한다. (모든 생성자는 상위 클래스의 생성자를 명시적으로든 아니면 묵시적으로든 호출할 수 있어야 하기 때문에)
댓글 없음:
댓글 쓰기