strong typed language의 장점은 이름처럼 타입 안정성을 보장해준다는 것이다. 타입이 서로 구분되고 각각 다른 의미를 갖는다. 그래서 더욱더 다양하게 type들을 구분할 수 있도록 해주지만 반대로 Object
도 존재한다.
typed language에서 Object
클래스는 존재하지 않아야 할것 같지만 이미 존재하고 있다. Object
는 가장 높은 추상화 수준을 제공하고 서로 다름을 제거하고 동일하게 보이게 노력한다. 그렇기때문에 다음과 같이 타입안전성을 해친다.
ArrayList<Object> objects = new ArrayList<>();
objects.add("this is string");
objects.add(11);
objects.add(11.1f);
그럼 대체 왜 Object
는 어떻게 사용해야 할까?
이미 언급한것과 같이 Object
는 높은 추상화 수준을 제공한다. 복잡도를 낮추고 확장성을 높여준다. 하지만 타입 안정성도 해치고, 의존관계를 복잡하게 만들기도 한다.
getClass()
는 객체의 타입 정보를 얻을 수 있다.
이 Class 오브젝트는 다음과 같이 isAssignableFrom
메소드를 제공한다. this
class에 object를 assign할 수 있는지 검사하는 메소드이다. 또한 javadoc의 내용을 보면 다음 같이 this
Class를 다른 타입으로 conversion을 하는데 사용한다라는 내용도 있다.
하지만 이것은 타입 안정성을 해치는 코드를 작성할 수 있게 만들고, 무엇보다도 추상체가 구현체를 참조하는 의존성을 만들 가능성이 커진다.🙈
// package base
class Policy
class Context {
public void policy(Object policyObject) {
if(Policy.getClass().isAssignableFrom(policyOject.getClass())) {
AppPolicy appPolicy = (AppPolicy)policyOjbect; // ???
}
}
}
//-----
// package application
class AppPolicy extends Policy
추상체에서 구현체의 의존관계를 만들지 않으면서도 추상화된 구현체를 구분하는 용도로만 한정한다면 Object
를 이용한 높은 추상화를 유지하면서 타입 안정성도 함께 제공할 수 있다. 추상화된 구현체를 조작해야 한다면 구현체 레벨에서 처리되도록 위임해야 할 것이다.
다음은 SpringBoot의 AbstractSecurityInterceptor의 코드 일부이다.
179라인에서 입력받은 객체가 어떤 객체인지 알지 못한다. 다만 SecurityObject의 어떤 관계(여기서는 상속관계)인지만 확인하고, 구현체에 대한 처리가 필요한 부분은 186라인에서 위임한다.