在Scala中,假设我有一个这样的案例类:
case class Sample(myInt: Int, myString: String)
Run Code Online (Sandbox Code Playgroud)
有没有办法让我获得一个Seq[(String, Class[_])]或更好的Seq[(String, Manifest)]描述案例类的参数?
对于如何在没有过多样板的情况下在Scala中高效序列化的问题,Twitter-chill看起来是一个很好的解决方案.
但是,我没有看到他们如何处理案例类的任何证据.这是自动工作还是需要做某些事情(例如创建一个零参数构造函数)?
我对WireFormatScoobi内置的序列化机制有一些经验,这是一个类似于Scalding的Scala Hadoop包装器.它们具有最多22个参数的case类的序列化程序,这些参数使用apply和unapply方法,并对这些函数的参数进行类型匹配以检索类型.(这在Kryo/chill中可能没有必要.)
我必须在这里遗漏一些愚蠢的东西.我有这个:
case class Color(val rgb:Int) {
private val c = rgb - 0xff000000
val r = (c & 0xff0000) >> 16
val g = (c & 0x00ff00) >> 8
val b = (c & 0x0000ff)
}
case object Red extends Color(0xffff0000)
case object Green extends Color(0xff00ff00)
case object Blue extends Color(0xff0000ff)
Run Code Online (Sandbox Code Playgroud)
然后我希望这打印真实:
val c = Color(0xff00ff00)
println(c == Green)
Run Code Online (Sandbox Code Playgroud)
为什么不呢?
我正在制作一个通过反射字段值设置的 Scala 应用程序。这工作正常。
但是,为了设置字段值,我需要一个创建的实例。如果我有一个带有空构造函数的类,我可以使用 classOf[Person].getConstructors 轻松做到这一点....
但是,当我尝试使用具有非空构造函数的 Case 类执行此操作时,它不起作用。我拥有所有字段名称及其值,以及我需要创建的对象类型。我可以用我所拥有的以某种方式实例化 Case Class 吗?
我唯一没有的是来自 Case Class 构造函数的参数名称,或者一种在没有参数的情况下创建它然后通过反射设置值的方法。
我们来看例子。
我有以下
case class Person(name : String, age : Int)
class Dog(name : String) {
def this() = {
name = "Tony"
}
}
class Reflector[O](obj : O) {
def setValue[F](propName : String, value : F) = ...
def getValue(propName : String) = ...
}
//This works
val dog = classOf[Dog].newInstance()
new Reflector(dog).setValue("name", "Doggy")
//This doesn't
val person = classOf[Person].newInstance //Doesn't work
val ctor …Run Code Online (Sandbox Code Playgroud) 我想回答这个问题.
而不是写:
case class Person(name: String, age: Int) {
def this() = this("",1)
}
Run Code Online (Sandbox Code Playgroud)
我以为我会使用宏注释来扩展它:
@Annotation
case class Person(name: String, age: Int)
Run Code Online (Sandbox Code Playgroud)
所以我尝试DefDef在宏注释的impl中使用quasiquotes 将新构造函数添加为普通的,如:
val newCtor = q"""def this() = this("", 1)"""
val newBody = body :+ newCtor
q"$mods class $name[..$tparams](..$first)(...$rest) extends ..$parents { $self => ..$newBody }"
Run Code Online (Sandbox Code Playgroud)
但是这会返回一个错误: called constructor's definition must precede calling constructor's definition
有办法解决这个问题吗?我错过了什么?
谢谢你看看,朱利安
我有一个案例类定义如下:
case class StreetSecondary(designator: String, value: Option[String])
Run Code Online (Sandbox Code Playgroud)
然后我定义一个显式的伴侣对象:
object StreetSecondary {
//empty for now
}
Run Code Online (Sandbox Code Playgroud)
定义显式伴随对象StreetSecondary的行为导致编译器生成"隐含伴随对象"丢失; 即替换为无法访问编译器生成的版本.例如,该tupled方法可通过此隐式伴随对象在案例类StreetSecondary上使用.但是,一旦我定义了显式伴随对象,该tupled方法就会"丢失".
那么,我需要定义/添加/更改上面的StreetSecondary显式伴随对象,以重新获得所有丢失的功能,并替换编译器提供的隐式伴随对象?我想要的不仅仅是tupled恢复的方法.我想要unapply恢复所有功能(例如,包括提取器/ ).
感谢您提供的任何指导/指导.
更新1
我已经做了足够的搜索来发现几件事:
A)必须在其案例类之前定义显式伴随对象(至少在Eclipse Scala-IDE工作表中就是这种情况,并且代码在IntelliJ IDE的工作表中不起作用,无论哪个先出现).
B)有一个强制tupled工作的技术技巧(谢谢drstevens):(StreetSecondary.apply _).tupled虽然这解决了特定的tupled方法问题,但它仍然没有准确或完整地描述scala编译器在隐式伴随对象中提供的内容.
C)最后,可以定义显式伴随对象以扩展与主构造函数的参数的签名匹配的函数,并返回案例类的实例.它看起来像这样:
object StreetSecondary extends ((String, Option[String]) => StreetSecondary) {
//empty for now
}
Run Code Online (Sandbox Code Playgroud)
同样,我仍然不能准确或完整地描述scala编译器在隐式伴随对象中提供的内容.
我有一个包含许多成员的案例类,其中两个是非原始的:
import com.twitter.util.Duration
case class Foo(
a: Int,
b: Int,
...,
y: Int,
z: Int,
timeoutSeconds: Duration,
runtimeMinutes: Duration)
Run Code Online (Sandbox Code Playgroud)
我想将以下JSON反序列化为此case类的实例:
{
"a": 1,
"b": 2,
// ...
"y": 42,
"z": 43,
"timeoutSeconds": 30,
"runtimeMinutes": 12,
}
Run Code Online (Sandbox Code Playgroud)
通常,我会写json.extract[Foo].然而,MappingException由于timeoutSeconds和,我得到了明显的runtimeMinutes.
我看过FieldSerializer,它允许在AST上进行字段转换.但是,它不够,因为它只允许AST转换.
我也看过扩展CustomSerializer[Duration],但没有办法反省哪个JSON密钥正在被处理(timeoutSeconds或runtimeMinutes).
我也可以尝试延长CustomSerializer[Foo],但后来我将有很多的样板代码,用于提取值a,b,..., z.
理想情况下,我需要一些PartialFunction[JField, T]作为反序列化器的东西,以便我可以写:
{
case ("timeoutSeconds", JInt(timeout) => timeout.seconds
case ("runtimeMinutes", JInt(runtime) => …Run Code Online (Sandbox Code Playgroud) 一些嵌套的case类和字段addresses是Seq[Address]:
// ... means other fields
case class Street(name: String, ...)
case class Address(street: Street, ...)
case class Company(addresses: Seq[Address], ...)
case class Employee(company: Company, ...)
Run Code Online (Sandbox Code Playgroud)
我有一名员工:
val employee = Employee(Company(Seq(
Address(Street("aaa street")),
Address(Street("bbb street")),
Address(Street("bpp street")))))
Run Code Online (Sandbox Code Playgroud)
它有3个地址.
而且我想把街道开头只用"b"开头.我的代码很乱如下:
val modified = employee.copy(company = employee.company.copy(addresses =
employee.company.addresses.map { address =>
address.copy(street = address.street.copy(name = {
if (address.street.name.startsWith("b")) {
address.street.name.capitalize
} else {
address.street.name
}
}))
}))
Run Code Online (Sandbox Code Playgroud)
该modified员工则:
Employee(Company(List(
Address(Street(aaa street)),
Address(Street(Bbb street)),
Address(Street(Bpp street))))) …Run Code Online (Sandbox Code Playgroud) 特定
case class Fruit(name: String, colour: String)
Run Code Online (Sandbox Code Playgroud)
我想弃用案例类字段colour.
我试图通过使用Scala来实现前者 @deprecated
case class Fruit(name: String, @deprecated("message", "since") colour: String)
Run Code Online (Sandbox Code Playgroud)
和Java @Deprecated注释
case class Fruit(
name: String,
/* @Deprecated with some message here */
@(Deprecated @field)
colour: String
)
Run Code Online (Sandbox Code Playgroud)
不幸的是,我无法colour在任何情况下弃用,我无法找到任何资源.
实际上,我可以使用其他方法实现相同的任务,例如将我的case类放宽到普通类并提供getterfor colour并使后者弃用,但我想知道是否实际上不可能弃用case类字段而且 -最终 - 原因.
谢谢.
UPDATE
正如迈克正确指出的那样,colour是一个案例类的必填字段,因此设置此属性的意义deprecated是有争议的.我想弃用colour,因为我现在提供colour来自另一个构造的信息,我想让用户知道这colour不是获取该信息的正确实例,我将Fruit在下一个版本中将其删除.
到目前为止,我只是警告用户不要colour从Fruit属性中获取信息,暂时,我并不关心他们是否可以创建带有颜色信息的水果实例.
更新2
正如阿列克谢所说,我在编译时确实有被弃用的警告.但是为什么我不能在IDE代码中观察到弃用以及我弃用某个方法呢?我期待以下的东西
val fruit = Fruit("peer", "green")
val colour = fruit. …Run Code Online (Sandbox Code Playgroud) 我正在编写一个类型安全的代码,并希望用我自己的实现替换apply()为case classes生成的代码。这里是:
import shapeless._
sealed trait Data
case object Remote extends Data
case object Local extends Data
case class SomeClass(){
type T <: Data
}
object SomeClass {
type Aux[TT] = SomeClass { type T = TT }
def apply[TT <: Data](implicit ev: TT =:!= Data): SomeClass.Aux[TT] = new SomeClass() {type T = TT}
}
val t: SomeClass = SomeClass() // <------------------ still compiles, bad
val tt: SomeClass.Aux[Remote.type] = SomeClass.apply[Remote.type] //compiles, good
val ttt: SomeClass.Aux[Data] = …Run Code Online (Sandbox Code Playgroud) case-class ×10
scala ×10
reflection ×2
scala-macros ×2
constructor ×1
equality ×1
haskell-lens ×1
json ×1
json4s ×1
kryo ×1
macros ×1
shapeless ×1
twitter ×1
type-safety ×1