2015-02-06 1 views
2

나는 그것을 확장하는 추상 클래스와 몇 가지 구체적인 클래스를 가지고있다.자바, 상속 클래스에서 특정 추상 클래스 생성자를 호출하지 못하도록하는 방법은 무엇입니까?

추상 클래스에는 두 개의 생성자가 있습니다. 하나의 특정 클래스에서 호출 할 수있는 생성자 중 하나를 원합니다.

(I 자바 상태 머신에 대한 enum 패턴에 대해 알고 있지만, 서브 클래스 (불변 POJO를) 두 가지 수준의 내가 해결하고있어 문제에 대한 더 나은 작동합니다.) 내가 만들고 싶어

public abstract class SuperState { 
    public final long mValue; 
    protected SuperState(long value) { mValue = value; } 
    protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
    ... 
} 

public class FirstState extends SuperState { 
    public FirstState() { super(0); } 
    ... 
} 

public class SecondState extends SuperState { 
    public SecondState(SuperState last) { super(last); } 
    ... 
} 

public class ThirdState extends SuperState { 
    public ThirdState(SuperState last) { super(last); } 
    ... 
} 

SuperState(long value) 생성자를 호출하기위한 서브 클래스 (FirstState은 제외)에 대한 컴파일 타임 (또는 적어도 런타임) 오류.

SuperState 생성자에서 생성되는 구체 클래스의 유형을 알아낼 수 있고 예상대로 작동하지 않으면 런타임 예외가 발생합니까?

추상 클래스에 대해 "기본"구체적인 클래스가있어서 추가 액세스 형식이 있습니까? 내가 못생긴 찾을 수 있지만 내가 생각할 수있는

+1

나는 이것이 가능하다고 생각하지 않는다 "정상적인"방법으로. 그러나'FirstState'를'SuperState'와 같은 패키지로 옮기고'protected SuperState (long)'* package-private *을 만들 수 있습니다. 그러나 이것이'SecondState'를 움직일 가능성을 막을 수는 없습니다. – Tom

답변

3

난 당신이하고있는 명확하게 모르는 것 같아요. SuperState에는 특정 구현에서 호출 할 수있는 생성자가 있다는 것을 알 수 있습니다. 왜? 하위 클래스가 특별합니까? 왜 다른 구현은 그것을 호출해서는 안됩니까? FirstState는 특별한 경우

는, 어쩌면 당신은 내부 클래스로 갖고 싶어 :

public abstract class SuperState { 
    public final long mValue; 
    private SuperState(long value) { mValue = value; } 
    protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
    ... 
    public static class FirstState { 
    //Can call SuperState(long) from here 
    } 
} 

이 그때 아마 당신이 열려 모두 생성자를 떠나야한다, 당신에게 적절한하지 못하는 경우. 는, 당신이 체인 같은 구조를 만들고있어 나에게 보인다, 당신은 아마 접근 클래스로 FirstState을 갖고 싶어하지 않는 경우 :

public abstract class SuperState { 
    public final long mValue; 
    private SuperState(long value) { mValue = value; } 
    protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
    ... 
    private static class FirstState extends SuperState { 
    private FirstState() { super(0); } 
    } 
    public static SuperState getFirstState() { return new FirstState(); } 
} 
+0

Best Answer now.예, 조금 사슬처럼 - 상태의 생성자 (계층 구조의 각 수준에서)는 마지막 상태의 데이터를 최상위 복사 (및 수정)해야 할 수 있습니다. 건설 후 체인이 없습니다. 더 유사한 두 상태 (더 많은 수퍼 클래스가 공통) 일수록 더 많은 데이터가 전파됩니다. – fadedbee

+0

자바가 '친구'가 아니기 때문에 내가 원하는 것은 아니지만 가능한 옵션 중에서 최고입니다. – fadedbee

+0

친구의 유스 케이스 인 경우 친구 시뮬레이션 패턴을 사용해야합니다. http://stackoverflow.com/questions/182278/is-there-a-way-to-simulate-the-c-friend-concept- in-java. 내 대답의 시작 부분에 올린 제안은, 당신이 필요로하는 추상적 인 개념 인 적어도 자신에게 더 명확하게해야한다는 것입니다. 그런 다음 그것을 바탕으로 구현을 결정하십시오. –

2

한 가지 방법은 :

protected SuperState(long value) 
{ 
    if (!this.getClass().getName().equals("SomeConcreteClassName")) 
     throw new SomeException(); 
    mValue = value; 
} 

비록 초 국가와 같은 패키지의 FirstState 클래스를 넣고 패키지 개인 액세스를 사용하는 방법에 대한 톰의 의견은 더 나은 소리.

+0

작동하지만 컴파일시 오류가 발생하지 않습니다. – BretC

+0

@Bret 글쎄, OP는 컴파일 타임 또는 런타임 오류 중 하나를 요청했습니다. 나는 컴파일 시간 오류가 더 좋을 것이라는데 동의한다. – Eran

+0

죄송합니다, 오인해야합니다 – BretC

2

나는 그것을 달성하는 유일한 방법은 "친구"의 아날로그를 사용하는 것이라고 생각합니다. 트릭은 FirstState으로만 구성 할 수있는 FirstState에 전용 Value 클래스를 갖는 것입니다. 다른 클래스는 FirstState.Value 클래스를 볼 수는 있지만 클래스를 인스턴스화 할 수는 없습니다.

abstract class SuperState { 
    public final long mValue; 
    protected SuperState(FirstState.Value value) { mValue = value.value; } 
    protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
} 

class FirstState extends SuperState { 
    public static class Value { private Value() {} } 
    private static Value value = new Value(); 

    public FirstState() { super(value); } 
} 

class SecondState extends SuperState { 
    public SecondState(SuperState last) { super(last); } 
} 
2

이 같은 기본 액세스 한정자와 함께 할 수 있습니다

package a; 

public abstract class SuperState { 
    public final long mValue; 
    SuperState(long value) { mValue = value; } // constructor has default access modifier 
    protected SuperState(SuperState last) { mValue = last.mValue + 1; } 
    ... 
} 



package a; 

public class FirstState extends SuperState { 
    public FirstState() { super(0); } 
    ... 
} 



package b; 
// is not able to access constructor SuperState(long) ie. calling contructor 
// SuperState(long) will result in compile time error 
public class SecondState extends SuperState { 
    public SecondState(SuperState last) { super(last); } 
    ... 
} 
관련 문제