문제

기본 클래스 B와 파생 클래스 D가 있다고 가정 해 봅시다. 인스턴스가 어떤 유형이든 새로운 객체를 반환하는 기본 클래스 내에 메소드 foo ()를 갖고 싶습니다. 예를 들어, b.foo ()를 호출하면 b 형의 객체를 반환하고 d.foo ()를 호출하면 d 형의 객체를 반환합니다. 한편, 구현은 전적으로 기본 클래스 B에 있습니다.

이게 가능해?

도움이 되었습니까?

해결책

하지 않다. "foo"방법을 추상화하십시오.

abstract class B {
    public abstract B foo();
}

또는 기본 클래스 생성자를 통해 추상 공장을받습니다.

abstract class B {
    private final BFactory factory;
    protected B(BFactory factory) {
        this.factory = factory;
    }
    public B foo() {
        return factory.create();
    }
}
interface BFactory {
    B create();
}

맛에 공분산 반환 유형과 제네릭을 추가하십시오.

다른 팁

각 클래스에 기본 생성자가있는 한

    public B instance() throws Exception {
        return getClass().newInstance();
    }

글쎄, 나는 꺼질 수 있지만 "이"는 항상 현재 객체를 지칭하기 때문에 다음과 같은 것을 할 수 있다고 가정합니다.

public B foo() {
    return this.getClass().newInstance();
}

아니면 그 줄을 따라 뭔가? D의 인스턴스를 작성한 다음 d.foo ()를 호출하는 경우 B로 반환 된 인스턴스를 B로 반환해야합니다.이 경우에 가능한 한 구체적으로해야한다고 생각합니다.

이것을 달성하려면 디자인 결함이 있다고 생각하는 것 외에도 다음 접근법을 시도 할 수 있습니다.

질문에서 정적 (클래스) 메소드, b.foo (), d.foo ()를 사용하고 있습니다. 정적 메소드는 동적 특성을 가지지 않기 때문에 상속을 사용하여 달성 할 수 없으며 조회에 참여하지 않습니다. 체계. 따라서 유형 정보가 충분하지 않습니다.

멤버 함수를 사용하는 경우 foo ()는 다음 구성을 가질 수 있습니다.

public class B {
    public B foo()
    throws IllegalAccessException, InstantiationException {
        return this.getClass().newInstance();
    }
}

public class D  extends B{    
}

public class Test {
    public static final void main(String[] args)
    {
        try {
            System.out.println((new B()).foo());
            System.out.println((new D()).foo());
        } catch (IllegalAccessException e) {
            e.printStackTrace();  
        } catch (InstantiationException e) {
            e.printStackTrace();  
        }
    }
}

다른 답변에서 알 수 있듯이, 각 서브 클래스에 무사 구조물이있는 경우 getClass (). newInstance ()를 사용할 수 있습니다 (InstantiationException 및 OrgalAccessException을 찾아야 함).

생성자가 인수를 요구하는 경우, 반사를 사용하거나 (내 견해에서 선호하는) getNewInstance ()와 같은 메소드를 정의 할 수 있으며 필요한 경우에만 하위 클래스에서 대체 할 수 있습니다.

예를 들어

Thing foo() {
    Thing th = getNewInstance();
    // do some stuff with th
    return th;
}

Thing getNewInstance() {
    return getClass().newInstance();
}

그런 다음 기본 생성자가없는 서브 클래스의 경우 실제로 필요한 경우에만 getNewInstance ()를 재정의 할 수 있습니다.

Thing getNewInstance() {
    return new BigThing(10, ThingSize.METRES);
}

나는 이것이 당신의 슈퍼 클래스에서 반사를 사용하여 가능할 것이라고 생각합니다.

public ClassName getFoo() throws InstantiationException, IllegalAccessException
{
    return getClass().newInstance();
}

여기서 Classname은 기본 클래스의 이름입니다.

당신은 당신이 그것을 사용하고 싶은 곳마다 그것을 캐스팅해야 할 것입니다 ... 나는 이것이 정말로 훌륭한 솔루션인지 확실하지 않습니다!

편집하다: NewInstance () 유형 메소드는 일반적으로 정적이며, 물론 서브 클래스의 유형이 정적 메소드를 사용하는 것에 대한 아이디어는 없습니다.

나는 얻을 방법이 없다고 생각한다 공전 메소드 서브 클래스 인스턴스를 (동적으로) 생성합니다.

@rik

글쎄, 실제 문제는 추상적 인 기본 클래스가 있다는 것입니다. 그리고 새로운 인스턴스를 반환하는 getnextthing ()이라는 메소드가 있습니다.

그런 다음 Bigthing, Littlething, Something과 같은 여러 하위 클래스가 있으며 각각의 GetNextThing () 메소드를 계속 다시 작성하고 싶지 않습니다. 그들은 모두 똑같이하기 때문에 낭비되는 것 같습니다 ...

내 접근 방식이 잘못 되었습니까?

왜 당신이 실제로하려고하는 일을하려고하는지 잘 모르겠습니다. 더 많은 맥락을 제공하면 더 많은 도움을 줄 수 있습니다.

public class B <X extends B>{

public X foo() throws InstantiationException, IllegalAccessException{
    return (X)this.getClass().newInstance();
}
}        
public class C extends B<C>{        

}

이 조언을 제공하겠습니다. CS 수업을 가르치는 경향은 교수들이 상속에 매료되었지만 구성을 알아 내지 못했다는 것입니다. 나는 당신이 찾고있는 것이 구성이라고 생각합니다. 그래서 그 자체로 getnextthing을 부르는 대신, 당신은 일을 구현하는 것에 대해 생각해야 할 것입니다. 반복적 인

이것은 당신이 단지 써야한다는 것을 의미합니다 반복자 상속 모델에 맞지 않는 것처럼 보이므로 다음 사항을 얻는 논리를 캡슐화 할 수 있습니다. 이것의 또 다른 장점은 당신이 이것으로부터 멋진 구문 장치를 얻는다는 것입니다 (루프 이해력을 위해 향상).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top