저는 API 디자인을 연구하고 있습니다. 지금까지 생각하지 못했던 Java 및 다형성에 대해 뭔가 있습니다. 나는이 같은 API를 만드는 경우 :Java, 다형성, 정적 입력 및 "QueryInterface"패턴
interface FooFactory
{
public Foo getFoo();
}
interface Foo
{
public void sayFoo();
}
는 내 FooFactory
구현을 제공하기 위해 의존 할 수있는 유일한 일은 Foo
구현입니다. 나는 다음과 같이 몇 가지 개선 된 방법을 제공하기로 결정하는 경우 :
interface EnhancedFoo extends Foo
{
public void patHeadAndRubBelly();
}
class EnhancedFooImpl implements EnhancedFoo
{
... implementation here ...
}
class EnhancedFooFactoryImpl implements FooFactory
{
@Override public EnhancedFoo getFoo() { return new EnhancedFooImpl(); }
}
을하고 그들이 Foo
인터페이스를 획득하고 EnhancedFoo
로 캐스팅하려고하면 내 API 클라이언트가 EnhancedFoo
인터페이스를 사용할 수있는 유일한 방법입니다.
HRESULT QueryInterface(
[in] REFIID riid,
[out] void **ppvObject
);
아이디어는 당신이 성공하면, 당신은 당신을 보장하는 포인터를 얻을, 당신이 원하는 인터페이스에 대한 GUID를 전달한다는 것입니다 :
나는 마이크로 소프트가 IUnknown
인터페이스에서 COM을 처리하는 방법을 기억 찾고 있던 인터페이스로 안전하게 전송할 수 있습니다.
내가 자바 형태 보증 된 방법으로 비슷한 뭔가를 할 수 : 나도 원하는 서브 인터페이스의 인스턴스를 반환하거나 사용할 수없는 경우는 null 반환 요청에 대한 구현을 제공
interface FooFactory
{
public <T extends Foo> T getFoo(Class<T> fooClass);
}
.
내 질문입니다 :
- 는 QueryInterface를 패턴은 합리적이다?
- 그냥 캐스팅을 사용해야합니까?
- 또는 클라이언트가 문제의 일반 메소드를 엄격하게 사용하도록 제한하기 위해 API에서 다형성을 처리하는 유일한 방법은 무엇입니까? (예를 들어, 내 예
Foo
의 방법이 아닌 모든EnhancedFoo
방법)
명확한 설명 : 공장 구현 클라이언트 코드에 의해 알려진하지 않을. (종속성 삽입 또는 Java의 ServiceLoader
또는 NetBeans Lookup
과 같은 일부 서비스 공급자 아키텍처를 사용한다고 가정 해 봅시다.) 클라이언트로서, 나는 무엇이 사용 가능한지 잘 모릅니다. 팩토리는 여러 개의 Foo
파생물에 액세스 할 수 있으며 클라이언트가 원하는 기능 세트를 요청할 수있게하고 그 중 하나를 가져 오거나 기본 Foo
기능으로 되돌려 야합니다.
내게 힘든 부분은 여기에 런타임 종속성이 있다는 것입니다. 모든 것이 컴파일 타임에 고정되어있는 순수 정적 유형 안전 접근 방식은 기본적인 Foo
기능에만 의존 할 수 있다는 것을 의미합니다. 그 접근법은 내게 친숙하지만, 가능한 향상된 기능을 놓치고 있습니다. 보다 역동적 인/기회 주의적 접근 방식은 이러한 기능을 활용할 수있는 것이지만,이를 사용하는 시스템을 설계하는 올바른 방법은 확실하지 않습니다.
Java 8에서 형식 유추가 향상되었습니다. – assylias
흠 ... 예외 접근 방식은 Python에서는 정상이지만 Java에서는 적합하지 않은 것처럼 보입니다. –
나는 그것이 완벽하게 적절하다고 말하고 싶다 - null-checking보다 좋다. – Arkadiy