2014-05-23 2 views
2

데이터가 서비스에서 이름 -> 값 쌍으로 나오고 모든 name-> value 유형이 문자열 인 경우에는 이상한 요구 사항이 있습니다 (실제로는 데이터가 저장되는 방식입니다)스칼라에서 타입 변환을 피하십시오

이것은 단순화 된 예입니다.

case class EntityObject(type:String,value:String) 

EntityObject("boolean","true") 

지금 나는 확실히 값을해야 EntityObject 유형은 "부울"경우 때문에 처음 밖으로 입력하고 해당 유형에 가치 캐스트 값을 확인할 수 아무것도하지만 부울이 아님을 가져올 때. 예를 들어,이 경우 체크 값은 부울이므로 유효성을 검사하려면 문자열 값을 부울 값으로 변환해야합니다. 부울 (boolean) 이외의 다른 것이라면 실패합니다.

예컨대 데이터가 아래와 같이 입력되면 전송이 실패하고이 오류에 대해 호출자에게 다시보고해야합니다.

EntityObject("boolean","1") 

이 때문에 이상한 요구 사항에 우아하고 유형 안전 프로그램에 대한 보이지 않는 유효성 검사 코드를 입력 변환을 강제로. 스칼라에서 이것을 처리하는 우아한 방법 (보다 안전한 형식 일 수 있음)?

+1

전송 하시겠습니까? 왜냐하면 캐스팅은'.asInstanceOf [..]'메소드로하는 일이기 때문입니다. 당신이 전환에 대해 말하는 것처럼 보입니다. –

답변

2

다음은이 곳의 매핑과 관련하여 Miles Sabin이 트윗에서 가져온 아이디어를 채널링하는 곳입니다 (this gist on github 참조). 객체 매핑의 유형이 시간의 머리 글자임을 알면 멋지게 사용할 수 있습니다 의존형을 포함하는 작은 트릭. 그것은 야생 타는 원인 ', 잠시만 :

trait AssocConv[K] { type V ; def convert: String => V } 

def makeConv[V0](name: String, con: String => V0) = new AssocConv[name.type]{ 
    V = V0 
    val convert = con 
} 

implicit val boolConv = makeConv("boolean", yourMappingFunc) 

def convEntity(name: String, value: String)(implicit conv: AssocConv[name.type]): Try[conv.V] = Try{ conv.convert(value) } 

나는이 시험하지 않았다 그러나 "해야한다"작동합니다. 또한 스칼라 Try에 동봉하여 변환 함수에 의해 발생한 예외를 catch합니다 (_.toInt을 변환기로 사용하는 경우를 대비하여).

+0

고마워. 이건 똑똑한 속임수이고 위대한 일을 할거야. def myFunc (entity : Entity, value : String) = convEntity (entity.eType, value) 전달 된 eType에 어떤 암시 적으로 사용할 지 모르기 때문에 컴파일에 실패합니다. 예 : 이 오류 : 매개 변수 전환에 대해 암시 적 값을 찾을 수 없습니다. \t AssocConv [entity.eType.타입] – user2066049

+0

@ user2066049 당신은 아이템이 잠재적으로 무엇이 될 수 있었는지 미리 알아야하고, 그것을 사용하여 아이템을 획득 할 수 있습니다. 임의의 엔티티 항목에 피드를 작성하는 코드를 작성하면 올바른 것입니다. 그것은 컴파일 시간 지식이 필요합니다. 따라서 기본적으로 코드를 작성해야 사전 정의 된 문자열과 비교할 수있는 컨텍스트로 평가할 수 있습니다. – wheaties

0

실제로 변환이 아닌 캐스팅에 대해 이야기하고 있습니다. 캐스팅은 값이 실제로 런타임시 부울의 인스턴스 인 반면, 가지고있는 것은 부울의 String 표현입니다.

사례 클래스로 이미 작업하고 있다면, 패턴 일치식이 여기서 잘 작동한다고 생각합니다. 예를 들어

하는 MatchError을 야기 지정된 패턴 중 하나와 일치하지 않거나, 당신이 당신의 자신의 예외를 던질 끝에 캐치 식을 넣을 수

def convert(entity : EntityObject) : Any = entity match { 
    case EntityObject("boolean", "true") => true 
    case EntityObject("boolean", "false") => false 
    case EntityObject("string", s) => s 
    // TODO: add Regex-based matchers for numeric types 
} 

아무것도.

이 특정 예제에서는 함수가 Any를 반환하므로 호출하는 커피가 특정 형식을 가져 오기 위해 실제 형식 캐스트를 수행해야하지만 적어도 그 시점까지는 모든 유효성 검사/변환이 이미 수행되었을 것입니다. 또는 값을 사용하는 코드를 위의 함수에 직접 넣고 캐스팅하지 않아도됩니다. 나는 당신의 구체적인 요구가 무엇인지 모릅니다. 그래서 나는 더 자세한 것을 제공 할 수 없습니다.

관련 문제