2010-05-07 4 views
4

자바 스크립트와 같이 느슨한 형식의 객체로 동작하는 클래스 (또는 동일한 인터페이스를 구현하는 클래스 세트)를 정의하려고합니다. 그들은 모든 종류의 데이터와 연산을 기본 유형에 따라 다룰 수 있습니다.런타임시 형식 확인을위한 Java 베스트 프랙티스

세 가지 다른 방식으로 작동하지만 이상적인 것은 없습니다. 이 테스트 버전은 문자열과 정수 만 허용하며 유일한 연산은 add입니다. 정수를 추가하면 정수 값의 합계가 생기고 문자열을 추가하면 문자열이 연결되고 문자열에 정수를 추가하면 정수가 문자열로 변환되어 문자열과 연결됩니다. 최종 버전에는 더 많은 유형 (Doubles, Arrays, 새 속성을 동적으로 추가 할 수있는 JavaScript와 유사한 객체) 및 더 많은 작업이 포함됩니다.

방법 1 : DynString1

에 대한

public interface DynObject1 { 
    @Override public String toString(); 
    public DynObject1 add(DynObject1 d); 
    public DynObject1 addTo(DynInteger1 d); 
    public DynObject1 addTo(DynString1 d); 
} 


public class DynInteger1 implements DynObject1 { 
    private int value; 

    public DynInteger1(int v) { 
    value = v; 
    } 

    @Override 
    public String toString() { 
    return Integer.toString(value); 
    } 

    public DynObject1 add(DynObject1 d) { 
    return d.addTo(this); 
    } 

    public DynObject1 addTo(DynInteger1 d) { 
    return new DynInteger1(d.value + value); 
    } 

    public DynObject1 addTo(DynString1 d) 
    { 
    return new DynString1(d.toString()+Integer.toString(value)); 
    } 
} 

... 및 이와 유사한

방법 2 : 공용 인터페이스의 DynObject2 { @Override 공공 문자열 toString(); public DynObject2 add (DynObject2 d); } DynString2

에 대한

public class DynInteger2 implements DynObject2 { 
    private int value; 

    public DynInteger2(int v) { 
    value = v; 
    } 

    @Override 
    public String toString() { 
    return Integer.toString(value); 
    } 

    public DynObject2 add(DynObject2 d) { 
    Class c = d.getClass(); 

    if(c==DynInteger2.class) 
    { 
     return new DynInteger2(value + ((DynInteger2)d).value); 
    } 
    else 
    { 
     return new DynString2(toString() + d.toString()); 
    } 
    } 
} 

... 및 이와 유사한

방법 3 : 대신 내가 value.getClass()를 사용 == 수 있다면 - 다른 논리 Integer.class와

public class DynObject3 { 

    private enum ObjectType { 
    Integer, 
    String 
    }; 

    Object value; 
    ObjectType type; 

    public DynObject3(Integer v) { 
    value = v; 
    type = ObjectType.Integer; 
    } 

    public DynObject3(String v) { 
    value = v; 
    type = ObjectType.String; 
    } 

    @Override 
    public String toString() { 
    return value.toString(); 
    } 

    public DynObject3 add(DynObject3 d) 
    { 
    if(type==ObjectType.Integer && d.type==ObjectType.Integer) 
    { 
     return new DynObject3(Integer.valueOf(((Integer)value).intValue()+((Integer)value).intValue())); 
    } 
    else 
    { 
     return new DynObject3(value.toString()+d.value.toString()); 
    } 
    } 
} 

형식을 저장하지만 더 많은 형식으로 스위치 문을 사용하도록 변경하고 Java에서 클래스가 클래스를 사용하도록 허용하지 않습니다.

어쨌든 ... 내 질문은이게 뭐가 있는지에 대한 가장 좋은 방법은 무엇입니까?

+1

덧붙여 말하자면, Java 지식이 나를 망각시키지 않으면,'Class c = d.getClass(); if (c == DynInteger2.class)'는'if (d instanceof DynInteger2)'로 쓸 수 있습니다. – Thomas

답변

2

당신이하려는 것은 double dispatch입니다. 호출 된 메소드가 호출 된 객체의 런타임 유형과 해당 인수의 런타임 유형에 모두 의존하기를 원할 것입니다.

Java 및 기타 C 파생 제품 만 단일 발송을 지원하므로 옵션 1에서 사용했던 visitor pattern과 같은 kludge가 필요한 이유입니다. 이것이 일반적인 방법입니다. 리플렉션을 사용하지 않기 때문에이 방법을 선호합니다. 또한 파견 작업을 수행하는 큰 "교환기"방법을 사용하지 않고도 각 사례를 고유 한 방법으로 유지할 수 있습니다.

0

두 번째 옵션을 선택하고 세 번째 옵션을 선택하면 제네릭을 사용하는 것이 좋습니다. 따라서 해당 열거 형에 의존하지 마십시오. 그리고 첫 번째 옵션으로 남은 인생을위한 방법을 구현할 수 있습니다. 어쨌든 Class matching을 위해 "instanceof"연산자를 사용할 수 있습니다.