2012-02-14 1 views
2

Java에서 외부 프로그램을위한 새로운 스크립트 생성기를 만들고 있습니다. 이 언어는 변수를 지원하지만 형식이없는 언어입니다. 일반적으로 VAR 유형이 부동이다Java - 값 유형을 인식하는 패턴

public class Var 
{ 
    private String name; 
    private String type; 
    private float defaultValue; 
    private float lowerBound; 
    private float upperBound; 
    private float value; 
    private LinkedList<Float> valuesConstraint; 
    private String description; 
    private Category category; 
    private LinkedList<CvarDependency> dependencies; 
    ... 
} 

뿐만 아니라 부울 [0 | 1] 수 있으며, 문자열, 또는 INT :이 내가 처음 작성한 코드의 예입니다. 그래서 나는이 구현을 만들기 위해 결국 :

abstract class Var 
{ 
    private String name; 
    ... 
} 

public class IntVar extends Var 
{ 
    private int value; 
    private int defaultValue; 
    private int lowerBound; //-infinite 
    private int upperbound; //+infinite 
    ... 
} 

public class FloatVar extends Var 
{ 
    private float value; 
    private float defaultValue; 
    private float lowerBound; //-infinite 
    private float upperbound; //+infinite 
    ... 
} 

public class StringVar extends Var 
{ 
    private String value; 
    private String defaultValue; //empty string 
    ... 
} 

public class BoolVar extends Var 
{ 
    private boolean value; 
    private boolean defaultValue; 
    private boolean lowerBound; //false <-> 0 
    private boolean upperbound; //true <-> 1 
    ... 
} 

지금은 LinkedList의로 그 바르를 저장해야하지만, 내가 적절한 캐스팅을 관리하는 방법의 내용을 읽을해야 할 때? 이 접근법을 사용하는 것은 좋은 습관이 아니라고 읽었습니다.

Var var = Manager.getVar("namevar"); 
if(var.getClass().getName().equals("StringVar")) 
    ... 
else if(var.getClass().getName().equals("IntVar")) 
    ... 
else if(var.getClass().getName().equals("FloatVar")) 
    ... 
else if(var.getClass().getName().equals("BoolVar")) 
    ... 

이 문제를 해결하는 데 도움이되는 정보가 있습니까?

+0

각 Var에 대해 '방문자'패턴을 제안합니다. 그런 식으로 방문자는 캐스팅을하는 법을 압니다. –

+0

이것은 내가 필요한 패턴이다. 이 답글을이 게시글에 게시하여 답장 스택 맨 위에 넣을 수 있습니다! – Otacon

+0

instanceOf 연산자를 사용할 수 있습니까? – basav

답변

0

비교, 클래스의 클래스 이름을 비교하지 마십시오

if(var.getClass().equals(IntVar.class)) { 
    IntVar intVar = (IntVar) var; 
    ... 

또한 var instanceof IntVar을 사용할 수 있습니다,하지만 당신은 IntVar을 확장하는 클래스를 작성하는 경우이 문제가 발생할 수 있습니다.

+0

좋은, 고마워,하지만 그것은 "좋은 연습"??? :) – Otacon

+0

예, 그렇습니다. 그러나 비교 전에 var가 'null'이 아닌지 확인해야합니다. – Stephan

+0

Surely and thx;) – Otacon

0

당신은 제네릭 형식을 사용할 수 있습니다,하지만 난 당신이 회원들과 함께 무엇을해야하는지 모르겠어요 ...

public class Var<T extends Comparable<T>> 
{ 
    private String name; 
    private String type; 
    private T defaultValue; 
    private T lowerBound; 
    private T upperBound; 
    private T value; 
    private LinkedList<T> valuesConstraint; 
    private String description; 
    private Category category; 
    private LinkedList<CvarDependency> dependencies; 
    ... 
} 
+0

사실 몇 가지 조작을해야합니다. int, bool 및 float는 defaultValue, lowerBound, upperBound는 관리하지만 String은 관리하지 않습니다! – Otacon

0

보다는 당신의 통역 추출물을 가진 그리고 아마도 직접 값이 것입니다 운영 이 같은 방법으로 작업을 다른 접근 방식을 가지고 정의하는 것이 더 :

abstract class Var 
{ 
    ... 
    public Var add(Var var); // corresponds to var + otherVar; in script 
    public Var subtract(Var var); // corresponds to var - otherVar; in script 
    public Var unarySubtract(); // corresponds to -var; in script 
    ... 
} 

이러한 방법을 호출하여 스크립트 표현식을 평가할 수 있으며, 수업은 예를 들어 다음과 같이 무시하고 과부하 수있는이 방법 :

public class IntVar extends Var 
{ 
    ... 
    public IntVar add(IntVar var) 
    { 
     return new IntVar(value + var.value); // add another int 
    } 
    public FloatVar add(FloatVar var) 
    { 
     return new FloatVar(value + var.value); // add another float (and cast result to float? up to you whether you want to do this...) 
    } 
    public StringVar add(StringVar var) 
    { 
     return new StringVar("" + value + var.value); // add a string, and cast to string (for string concatenation) 
    } 
    public Var add(Var var) 
    { 
     throw new OperationNotSupportedException(); // no other types can be added to an IntValue so throw an exception 
    } 
    public Var subtract(Var var) {...} 
    public IntVar unarySubtract() 
    { 
     return new IntVar(-value); 
    } 
    ... 
} 

이렇게하면 인터프리터에서 직접 값을 처리하지 않고도이 작업을 구현하고 평가할 수 있습니다.

또 다른 장점은이 메서드를 사용하면 사용자가 잘못된 스크립트를 실행하려고 할 때 (예를 들어 BoolVar를 IntVar에 추가하려고 할 때) 인터프리터에서 예외가 발생한다는 것입니다.

아마도 당신은 그냥이 일 초록 바르 클래스 운영의 기본 구현을 할 수 : 작업의 안전한 사용과

public Var add(Var var) 
{ 
    throw new OperationNotSupportedException(); // no other types can be added to an IntValue so throw an exception 
} 

만 오버라이드/오버로드를.

여기에서 '내용 읽기'라고 말하면 아마도 출력을위한 것이라면 형식의 인스턴스 콘텐츠를 일정한 시점에서 일정한 방식으로 처리해야 할 것입니다. 추상 'toString()'메서드가 있습니까? 출력이 아닌 다른 목적을 위해 다른 목적으로 toX() 메서드를 사용하고 각 유형 인스턴스를 같은 방식으로 처리 할 수 ​​없다는 것이 어떤 목적입니까?

나는 이것이 당신의 질문에 직접적으로 대답하지 않는다는 것을 깨닫고, 당신이 달성하고자하는 것에 대해 어리석은 가정을했기 때문에이 문제를 완전히 피할 수 있기를 바라는 다른 접근법을 제안합니다./o 문제의 맥락을 더 많이 보았지만 그럼에도 불구하고 도움이되기를 바랍니다.

이 정보가 도움이되지 않는다면 좀 더 자세한 정보를 제공해주세요. 현재의 접근 방식을 계속 사용하는 것을 권장 할 수 없기 때문에 좀 더 자세한 정보를 제공하려고합니다.

편집 : 잠깐, 나쁘지 만 제대로 질문을 읽지 못했습니다. 이것은 통역사가 아니라 발전기입니다. 어떤 종류의 발전기입니까? 어떤 언어의 스크립트 생성기? 글쎄요, 중요한 문제는 아니지만, 이제는 제가 깨닫게 된 질문을 다시 읽었습니다. 저는 여러분이 성취해야 할 것에 대해 많이 이해하지 못한다는 것을 깨닫습니다.

캡슐화가 일반적으로 방문자 패턴보다 나은 선택이라고 생각합니다. :). 물론 Var가 제공하는 인터페이스를 통해 각 변수에 이미 첨부 된 동작에서 동작을 구성 할 수없는 방식으로 모든 변수에서 작동 할 수있는 동작을 추가해야하는 몇 가지 이유가없는 한 ... 이게 뭐야? 출력을 위해서는 반드시 각 변수를 모두 공통된 형식으로 읽을 수 있어야합니다. toString(), toSomething(), toAnotherThing() 등의 이유가 있어야합니다.

0

내 제안은 Visitor 패턴을 사용하는 것입니다. . 알고리즘은 객체 Var (및 하위 클래스)보다는 Visitor에 배치됩니다.

public class Var { 

    public void accept(VarVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

방문자

public interface VarVisitor { 
    public void visit(FloatVar var); 
    public void visit(IntVar var); 
    public void visit(StringVar var); 
    public void visit(BoolVar var); 

    //...etc. 
    public Object getValue(); 
} 

VisitorImpl는

public class VarVisitorImpl implements VarVisitor { 
    private Object value; 

    @Override 
    public Object getValue() { 
     return value; 
    } 

    @Override 
    public void visit(FloatVar var) { 

    } 

    @Override 
    public void visit(IntVar var) { 

    } 

    @Override 
    public void visit(StringVar var) { 

    } 

    @Override 
    public void visit(BoolVar var) { 

    } 
} 

나는 이것이 당신이 달성하고자하는 것에 대한 아이디어를 제공 바랍니다.