2010-01-20 4 views
2

다음 구조로 문자열의 매개 변수를 사용하여 새 클래스를 만들 수 있다는 것을 이해합니다.새 인스턴스를 사용하여 매개 변수가 필요한 클래스를 만드는 방법

Class<? extends Base> newClass = (Class<? extends Base>)Class.forName(className); 
Constructor<? extends Base> c = newClass.getConstructor(new Class[] {Manager.class, Integer.TYPE}); 
Base a = c.newInstance(new Object[] {this, new Integer(0)}); 

그러나 Base의 하위 클래스가 생성자를 사용하도록 보장하는 방법은 없을 것 같습니다.

이 상황을 처리하기위한 연습이 있습니까?

답변

1

생성자는 일반적인 방법과 다릅니다. 구현할 추상 생성자는 선언 할 수 없습니다. 즉, 하위 클래스를 인스턴스화하는 방법을 지정하지 않아도됩니다. 객체 지향 철학에서는 기본 클래스의 책임이 아닙니다.

원하는 경우 axtavt suggest와 같은 추상 초기화 메서드를 만들고 기본 클래스의 생성자에서 호출 할 수 있습니다. 그렇다면 적어도 전화가 걸릴 것입니다.

원하는 서명으로 생성자를 확인할 수도 있습니다. 찾지 못하면 클래스가 귀하의 조건을 어떻게 준수하지 않는지에 대한 예외를 던질 수 있습니다. 이 방법으로 리플렉션은 언어에 내장 된 것보다 약간의 힘을 줄 수 있습니다.

+0

감사합니다. 마지막 문장이 재미 있습니다. – Pool

2

하위 클래스별로 특정 생성자의 구현을 강제 적용 할 방법이 없습니다. Base 클래스의 작성자 인 경우 매개 변수와 함께 생성자를 사용하는 대신 일종의 init(Manager, int) 메서드를 선언 할 수 있습니다.

+0

+1. 그러나 하위 클래스가 초기화하는 데 추가 매개 변수가 필요한 경우 동일한 문제가 발생합니다. – Thilo

+0

고마워요. 그건 제가 생각한 것입니다.하지만 서브 클래스가 최종 속성을 이용할 수 없으므로이를 기각했습니다. – Pool

+0

@Thilo - 나는 그 시나리오에 대해 걱정하지 않는다. 하위 클래스가 추가 또는 다른 매개 변수를 가질 수 없다는 점을 강조하고 싶다. – Pool

2

매개 변수가 고정되어 있고 newInstance을 사용하려는 경우 하위 클래스에서 일치하는 생성자가 존재할 수 없다는 문제가 남아 있습니다. 컴파일러가이를 확인할 수있게하려면 팩토리 클래스를 사용하여 다음을 수행 할 수 있습니다. 원하는 매개 변수를 사용하여 createInstance 인 팩토리 인터페이스를 정의하고 직접 하위 클래스를 등록하는 대신 를 생성합니다

Class<? extends BaseFactory> newClass = 
     (Class<? extends BaseFactory>)Class.forName(factoryClassNameName); 
BaseFactory factory = newClass.getInstance(); 
Base a = factory.createInstance(this, 0); // no reflection necessary here 

당신이 구성 문자열에서 객체의 인스턴스를 생성해야하고, 일을 처리 할 수있는 매개 변수의 고정 된 수의 간단한 newInstance 전화보다 더 복잡 할 수 있다면

, 당신은 DI 컨테이너에 보일 것입니다. 이들 모두를 사용하면 매우 복잡한 방법으로 인스턴스를 만들 수 있습니다. 예를 들어 플랫 문자열로 인코딩하기 어려운 복잡한 개체 자체의 매개 변수를 사용하는 등의 여러 가지 방법으로 인스턴스를 만들 수 있습니다.

중간 접지는 속성을 사용하여 인스턴스를 구성합니다. 로깅 프레임 워크가 등록 정보 파일을 사용하여 다양한 구성 요소를 구성하는 방법을 예를 들어보십시오.

2

@axtavt가 맞습니다. 서브 클래스가 생성자에게 특정 서명을 제공하도록 강요 할 수 없습니다. (비 반사의 경우 Java 생성자가 다형성이 아니기 때문에 아무런 의미가 없습니다. 반사는 항상 약간 ... 추한 것입니다.)

다형성 객체를 만드는 방법을 원한다면 공장 패턴.

public interface BaseFactory { 
    Base create(int arg1, String arg2); 
    Base create(int arg1, float arg2); 
} 

public class Foo implements Base { .... } 

public class FooFactory implements BaseFactory { 
    public Base create(int arg1, String arg2) { 
     return new Foo(arg1, arg2); 
    } 
    public Base create(int arg1, float arg2) { 
     return new Foo(arg1, Float.toString(arg2)); 
    } 
} 

유일한 번거 로움은 factory 메소드의 반환 유형이 기본 유형이된다는 것입니다. 따라서 일반적으로 factory 메소드를 사용하면 생성 된 객체를 예상 된 하위 유형으로 캐스팅해야합니다. 당신은 아마 제네릭을 사용하여 이것을 피할 수 있습니다 ...

더하기 측면에서, 공장을 사용하면 처음에는 반사를 사용하지 않아도됩니다. 팩토리 인터페이스를 구현하는 경우 은 예상되는 시그니처가있는 메서드를 제공한다는 보증을 통해 팩터 메서드를 반영하여 호출 할 수 있습니다.

+0

+1 "유일한 번거 로움은 factory 메소드의 반환 유형이 기본 유형이된다는 것입니다." 괜찮을거야. 질문에서, 그는 또한 Base에 할당합니다. – Thilo

+0

흥미 롭습니다. 리플렉션을 피하는 것을 선호하지만 실제로 모든 가능한 클래스가 반드시 런타임에 사용 가능한 것은 아니므로 팩토리를 사용할 수는 없습니다. – Pool

+0

@ The Feast : 리플렉션을 사용하여 공장을로드합니다. 런타임에 필요한 모든 클래스를 사용할 수있는 것이 아니라면 클래스를로드하는 모든 방법이 실패합니다. – Thilo

관련 문제