Да, люди имеют. Для этого нужно использовать шаблон классов типов, предложенный Дэвидом Макивером sbinary и Дебасишем Гошем sjson . Трилогия Дебасиша
особенно полезны для всех промежуточных программистов Scala.
Сегодня многие библиотеки применяют эту методологию, включая мою scalaxb . См
Я позаимствовал идею именования у Scala Collections CanBuildFrom
и назвал мои классы типов следующим образом:
trait CanReadXML[A] {
def reads(seq: scala.xml.NodeSeq): Either[String, A]
}
trait CanWriteXML[A] {
def writes(obj: A, namespace: Option[String], elementLabel: Option[String],
scope: NamespaceBinding, typeAttribute: Boolean): NodeSeq
}
trait XMLFormat[A] extends CanWriteXML[A] with CanReadXML[A]
Редактировать
Не могли бы вы объяснить мне, как система выбирает между "с A" или "с B"?
Используя шаблон класса типов, библиотеки не смешиваются ни A
, ни B
.
Например, это скалярное устройство, которое предоставляет метод с именем scalaxb.fromXML
в объекте пакета, определенном следующим образом:
def fromXML[A](seq: NodeSeq, stack: List[ElemName] = Nil)
(implicit format: XMLFormat[A]): A = format.reads(seq, stack) match {
case Right(a) => a
case Left(a) => throw new ParserFailure(a)
}
Учитывая, что у вас есть XML-документ, и вы хотите демонтировать (десериализовать) его в ipo.Address
объект, вы бы вызвали
scalaxb.fromXML[ipo.Address](<shipTo xmlns="http://www.example.com/IPO">
<name>Foo</name>
<street>1537 Paper Street</street>
<city>Wilmington</city>
</shipTo>)
Объект Address
остается чистым, используя шаблон класса типов:
case class Address(name: String, street: String, city: String)
Как компилятор знает, что делать? Магия - это неявный параметр, требуемый fromXML
, который называется implicit format: XMLFormat[A]
. Это требует, чтобы у вас было XMLFormat[Address]
доступным как неявное значение в области, где вызывается scalaxb.fromXML[ipo.Address](...)
.
Это стало доступно в коде, сгенерированном scalaxb, потому что он смешивается в XMLProtocol
с объектом пакета пакета ipo
. И ipo.XMLProtocol
определяет
implicit lazy val IpoAddressFormat: scalaxb.XMLFormat[ipo.Address] = new DefaultIpoAddressFormat {}
Edit2
Я думаю, что начинаю понимать настоящий вопрос. У вас есть объект, состоящий из миксинов признаков, и вы хотите каким-то образом «десериализовать» композицию признаков в другом процессе.
Как вы уже писали, вы можете включить некоторые теги для каждой черты и загрузить все, что сможете.
Поскольку я уже писал о шаблонах классов типов, позвольте мне продолжить этот подход. Отличная вещь, связанная с наличием кода сериализации вне объекта, заключается в том, что вы могли бы фактически описать комбинацию смешанных объектов. Предположим, есть черты
trait Foo { def foo: Int }
trait Bar { def bar: Int }
и вы хотите описать миксин как <obj><foo>1</foo><bar>2</bar></obj>
.
Вот Суть Я взбил.
Я определил экземпляр класса типов для Foo
, Bar
и Foo with Bar
и вызвал
Def.fromXML[Foo with Bar](<obj><foo>1</foo><bar>2</bar></obj>)
вернул
Right(FooWithBar(1, 2))