2015-05-17 2 views
2

Я пытаюсь обойти стирание стилей и динамически преобразовывать список значений различных типов с использованием классов значений в json и обратно в соответствующие типы с помощью Json4s CustomSerializer. Однако я не смог динамически извлекать правильные значения. Из-за ссылки на AnyVal, я вынужден использовать value.toString при преобразовании в Json и сталкиваются с проблемами при воссоздании моих полей из json.классы стирания и значения scala типа

Я пробовал свою руку на scala в течение трех недель, поэтому я все еще изучаю веревки. Любая помощь будет оценена по достоинству.

abstract class MyVal { 
    def name: String 
    def value: AnyVal 
} 

trait Field { 
    def value: AnyVal 
} 

object Field { 
    def build(value: String): MyString = MyString(value) 
    def build(value: Int): MyInt = MyInt(value) 
    def build(value: Double): MyDouble = MyDouble(value) 
} 
case class MyString(val value: String) extends AnyVal with Field 
case class MyInt(val value: Int) extends AnyVal with Field 
case class MyDouble(val value: Double) extends AnyVal with Field 


object MyVal { 
    case class StringVal(name: String, value: MyString) extends MyVal 
    case class IntVal(name: String, value: MyInt) extends MyVal 
    case class DoubleVal(name: String, value: MyDouble) extends MyVal 

    def build(name: String, value: String): StringVal = StringVal(name, MyString(value)) 
    def build(name: String, value: Int): IntVal = IntVal(name, value) 
    def build(name: String, value: Double): DoubleVal = DoubleVal(name, value) 
} 


object Main { 
    def main(args: Array[String]) = { 
    var fields = Seq.empty[MyVal] 
    var row = Map("length" -> 1, "name" -> "test", "cost" -> 2.0) 
    var columns = Seq[String]("length", "name", "cost") 
    val fields: Seq[MyVal] = row foldLeft (Seq.empty[MyVal]) { 
     (previousFields: Seq[MyVal], currentField: Any) => { 
     columns map { 
      column => MyVal.build(column, Field.build(row(column))) 
     } 
     } 
    } 
    } 
} 

Методы сборки не устраняются правильно из-за двусмысленности.

ответ

2

Field черта определяет все типы possibl мы можем иметь для поля:

import scala.language.existentials 
import scala.language.implicitConversions 

sealed trait Field extends Any { 
    def value: Any 
} 

case class MyString(val value: String) extends AnyVal with Field 
case class MyInt(val value: Int) extends AnyVal with Field 
case class MyDouble(val value: Double) extends AnyVal with Field 

Обратите внимание на неявное def S ниже. Они позволяют преобразовывать значения известных типов в Field без использования build явно. Мы воспользуемся этим ниже.

object Field { 
    implicit def build(value: String): MyString = MyString(value) 
    implicit def build(value: Int): MyInt = MyInt(value) 
    implicit def build(value: Double): MyDouble = MyDouble(value) 
} 

Для MyVal нам не нужны конкретные подклассы - это было бы просто скопировать hiearchy из Field. Достаточно сказать, что каждое значение связано с Field - это захватывает ту же информацию.

sealed case class MyVal(name: String, value: Field) 

Мы можем определить implicits для возможности построить MyVal сек более легко, хотя мы не будем нуждаться в этом.

object MyVal { 
    // notice that we use the above Field.build.. implicits here: 
    implicit def build(name: String, value: String): MyVal = MyVal(name, value) 
    implicit def build(name: String, value: Int): MyVal = MyVal(name, value) 
    implicit def build(name: String, value: Double): MyVal = MyVal(name, value) 
} 

Я не был уверен, что вы пытаетесь выразить в своей main функции. Ниже приводится несколько более простой пример. Главный трюк здесь заключается в том, что вы не хотите иметь Map[String,Any]. Это никогда не сработает. Как только вы потеряете информацию о том, какие типы находятся на карте, вы не можете построить Field s и MyVal s вне ее без обработки некорректных значений. Вы хотите явно сохранить информацию о том, что значения являются только разрешенными, и это то, что для Field. Объявив Map[String,Field] и позволяя implicit s делать скучную работу для вас, вы получаете типобезопасный код ниже:

object Main { 
    def main(args: Array[String]) = { 
    val row = Map[String,Field]("length" -> 1, "name" -> "test", "cost" -> 2.0) 
    val vals: Seq[MyVal] = (for((k, v) <- row.iterator) yield MyVal(k, v)).toSeq 
    } 
} 

В частности, вы хотите, чтобы избежать иметь дело с типом стирания. Типированный код - ваше преимущество, тип стирания должен быть как можно больше оставлен на время выполнения.

+0

большое спасибо! – rreiki

Смежные вопросы