我正在制作一个通过反射字段值设置的 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) 我正在编写一个类型安全的代码,并希望用我自己的实现替换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类构造函数的参数,如果它们在某些测试中失败则抛出异常.当我尝试编写自己的apply方法时,编译器抱怨了(多个'apply'方法.
我想我可以把它变成一个非案例类,并自己做apply/unapply构造函数字段,但我希望不要这样做.
谢谢
根据scala规范,由case类构建的提取器如下(scala规范§5.3.2):
def unapply[tps](x: c[tps]) =
if (x eq null) scala.None
else scala.Some(x.xs11, ..., x.xs1k)
Run Code Online (Sandbox Code Playgroud)
出于实现原因,我希望能够在非案例类上模仿此提取器的行为.但是,我的实现无法重现相同的行为.
以下是我的差异示例:
trait A
sealed trait B[X <: A]{ val x: X }
case class C[X <: A](x: X) extends B[X]
class D[X <: A](val x: X) extends B[X]
object D {
def unapply[X <: A](d: D[X]): Option[X] =
if (d eq None) None
else Some(d.x)
}
def ext[X <: A](b: B[X]) = b match {
case C(x) => Some(x)
case D(x) => Some(x)
case _ …Run Code Online (Sandbox Code Playgroud) 我有一个case类,它的构造函数有一些参数,我定义了一个附带的类对象,它定义了一个带有不同参数集的替代构造函数,如下所示:
case class MyClass (c: Char, mc: List[MyClass])
object MyClass {
def apply(c: Char, mc: MyClass): MyClass = {
MyClass(c, List(mc))
}
}
Run Code Online (Sandbox Code Playgroud)
我想在一个:中使用原始的 case类构造函数foldRight:
object SomeStuff {
def problem (s: String) {
assert(!s.isEmpty)
val zero = MyClass('a', Nil)
val mc2 = "Pillsy Pillsy Pillsy" foldRight(zero) {
MyClass(_, List(_))
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我这样做时,我从编译器收到一条错误消息:"MyClass不接受参数." 如果我注释掉这一部分,val mc2 = ...这个问题就会消失,但MyClass显然是在定义参数中zero.我觉得我必须遗漏一些非常基本的东西,但我不知道它是什么.我已经尝试了几个解决方法,比如定义辅助方法或函数值作为第二个参数foldRight,但没有一个有用,这并不太令人惊讶,因为我基本上随意地摸索.
所以我有这样的事情:
abstract class Term
case class App(f:Term,x:Term) extends Term
case class Var(s:String) extends Term
case class Amb(a:Term, b:Term) extends Term //ambiguity
Run Code Online (Sandbox Code Playgroud)
一个术语可能如下所示:
App(Var(f),Amb(Var(x),Amb(Var(y),Var(z))))
Run Code Online (Sandbox Code Playgroud)
所以我需要的是Amb类所指示的所有变体.这用于表示模糊的解析林,我想键入检查每个可能的变体并选择正确的变体.在这个例子中我需要:
App(Var(f),Var(x))
App(Var(f),Var(y))
App(Var(f),Var(z))
Run Code Online (Sandbox Code Playgroud)
什么是在scala中创建这些变体的最佳方法?效率会很好,但并不是真正的要求.如果可能的话,我喜欢不使用反射.
"案例是" 特定情况的一个例子; 发生事情的一个例子 '.
所以我的问题是 - 为什么Scala'case'类被命名为'case'?有什么意义?为什么它是"案例",而不是"数据"类或其他什么?什么意思是'案例'在那.. ..案例:)
我已经定义了几个用于JSON表示的案例类,但是由于存在很多嵌套的案例类,因此我不确定我是否正确执行了。诸如spec,meta之类的实体的类型均为JSONObject以及Custom对象本身。
这是我定义的所有类:
case class CustomObject(apiVersion: String,kind: String, metadata: Metadata,spec: Spec,labels: Object,version: String)
case class Metadata(creationTimestamp: String, generation: Int, uid: String,resourceVersion: String,name: String,namespace: String,selfLink: String)
case class Spec(mode: String,image: String,imagePullPolicy: String, mainApplicationFile: String,mainClass: String,deps: Deps,driver: Driver,executor: Executor,subresources: Subresources)
case class Driver(cores: Double,coreLimit: String,memory: String,serviceAccount: String,labels: Labels)
case class Executor(cores: Double,instances: Double,memory: String,labels: Labels)
case class Labels(version: String)
case class Subresources(status: Status)
case class Status()
case class Deps()
Run Code Online (Sandbox Code Playgroud)
这是我需要转换的自定义K8s对象的JSON结构:
{
"apiVersion": "sparkoperator.k8s.io/v1alpha1",
"kind": "SparkApplication",
"metadata": {
"creationTimestamp": "2019-01-11T15:58:45Z",
"generation": 1,
"name": "spark-example", …Run Code Online (Sandbox Code Playgroud) 我创建了带有 100 个字段 +- 的 scala case 类,当我尝试构建项目(使用 gradle)时,出现错误:
Cause: java.lang.StackOverflowError
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:698)
at scala.tools.nsc.typechecker.Typers$Typer.runTyper$1(Typers.scala:5396)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedInternal(Typers.scala:5423)
Run Code Online (Sandbox Code Playgroud)
我正在使用 scala 2.11 ,发现过去有 22 个字段的限制。但它是固定的。
那么为什么构建失败呢?(我试图增加 -Xss20m ,但没有帮助)
我正在尝试copy()一个具有类型参数的 Scala 案例类。在呼叫站点,该值的类型为Foo[_]。
这按预期编译:
case class Foo[A](id: String, name: String, v1: Bar[A])
case class Bar[A](v: A)
val foo: Foo[_] = Foo[Int]("foo1", "Foo 1", Bar[Int](1))
foo.copy(id = "foo1.1")
Run Code Online (Sandbox Code Playgroud)
但是,如果我添加另一个 type 成员Bar[A],它将不再编译:
case class Foo[A](id: String, name: String, v1: Bar[A], v2: Bar[A])
case class Bar[A](v: A)
val foo: Foo[_] = Foo[Int]("foo1", "Foo 1", Bar[Int](1), Bar[Int](2))
foo.copy(id = "foo1.1") // compile error, see below
Run Code Online (Sandbox Code Playgroud)
type mismatch;
found : Playground.Bar[_$1]
required: Playground.Bar[Any]
Note: _$1 <: Any, but class …Run Code Online (Sandbox Code Playgroud) case-class ×10
scala ×10
extractor ×1
generics ×1
json ×1
kubernetes ×1
macros ×1
reflection ×1
scala-2.11 ×1
scala-macros ×1
shapeless ×1
type-safety ×1