score:0
I ran into a similar problem. Given the ease of using Macro Paradise, Macro Annotations are a solution (for scala 2.10.X and 2.11 so far).
Check out this question and the example project linked in the comments below.
score:2
The approach below works for any Scala class that has either a no-arg ctor or has an all defaulted primary ctor.
It makes fewer assumptions than some others about how much information is available at the point of call as all it needs is a Class[_] instance and not implicits etc. Also the approach does not rely on the class having to be a case class or having a companion at all.
FYI During construction precedence is given to the no-arg ctor if present.
object ClassUtil {
def newInstance(cz: Class[_ <: AnyRef]): AnyRef = {
val bestCtor = findNoArgOrPrimaryCtor(cz)
val defaultValues = getCtorDefaultArgs(cz, bestCtor)
bestCtor.newInstance(defaultValues: _*).asInstanceOf[A]
}
private def defaultValueInitFieldName(i: Int): String = s"$$lessinit$$greater$$default$$${i + 1}"
private def findNoArgOrPrimaryCtor(cz: Class[_]): Constructor[_] = {
val ctors = cz.getConstructors.sortBy(_.getParameterTypes.size)
if (ctors.head.getParameterTypes.size == 0) {
// use no arg ctor
ctors.head
} else {
// use primary ctor
ctors.reverse.head
}
}
private def getCtorDefaultArgs(cz: Class[_], ctor: Constructor[_]): Array[AnyRef] = {
val defaultValueMethodNames = ctor.getParameterTypes.zipWithIndex.map {
valIndex => defaultValueInitFieldName(valIndex._2)
}
try {
defaultValueMethodNames.map(cz.getMethod(_).invoke(null))
} catch {
case ex: NoSuchMethodException =>
throw new InstantiationException(s"$cz must have a no arg constructor or all args must be defaulted")
}
}
}
score:4
The case class should have default args, so that you can just Person()
; in the absence of a default arg, supplying a null for name might (or ought to) hit a require(name != null).
Alternatively, use reflection to figure out which params have defaults and then supply nulls or zeros for the rest.
import reflect._
import scala.reflect.runtime.{ currentMirror => cm }
import scala.reflect.runtime.universe._
// case class instance with default args
// Persons entering this site must be 18 or older, so assume that
case class Person(name: String, age: Int = 18) {
require(age >= 18)
}
object Test extends App {
// Person may have some default args, or not.
// normally, must Person(name = "Guy")
// we will Person(null, 18)
def newCase[A]()(implicit t: ClassTag[A]): A = {
val claas = cm classSymbol t.runtimeClass
val modul = claas.companionSymbol.asModule
val im = cm reflect (cm reflectModule modul).instance
defaut[A](im, "apply")
}
def defaut[A](im: InstanceMirror, name: String): A = {
val at = newTermName(name)
val ts = im.symbol.typeSignature
val method = (ts member at).asMethod
// either defarg or default val for type of p
def valueFor(p: Symbol, i: Int): Any = {
val defarg = ts member newTermName(s"$name$$default$$${i+1}")
if (defarg != NoSymbol) {
println(s"default $defarg")
(im reflectMethod defarg.asMethod)()
} else {
println(s"def val for $p")
p.typeSignature match {
case t if t =:= typeOf[String] => null
case t if t =:= typeOf[Int] => 0
case x => throw new IllegalArgumentException(x.toString)
}
}
}
val args = (for (ps <- method.paramss; p <- ps) yield p).zipWithIndex map (p => valueFor(p._1,p._2))
(im reflectMethod method)(args: _*).asInstanceOf[A]
}
assert(Person(name = null) == newCase[Person]())
}
score:5
If you are looking for a way to instantiate the object with no arguments, you could do the same as you did in your example, just so long as your reflection setter can handle setting the immutable vals.
You would provide an alternate constructor, as below:
case class Person(name : String, age : Int) {
def this() = this("", 0)
}
Note that the case class will not generate a zero-arg companion object, so you will need to instantiate it as: new Person()
or classOf[Person].newInstance()
. However, that should be what you are looking to do.
Should give you output like:
scala> case class Person(name : String, age : Int) {
| def this() = this("", 0)
| }
defined class Person
scala> classOf[Person].newInstance()
res3: Person = Person(,0)
Source: stackoverflow.com
Related Query
- How can I create an instance of a Case Class with constructor arguments with no Parameters in Scala?
- How to create a scala case class instance with a Map instance
- How can I use Json.reads to deserialize JSON into a case class with optional constructor parameters
- How can I extract values from a String to create a case class instance in Scala
- How to create a Scala class with private field with public getter, and primary constructor taking a parameter of the same name
- How do I add a no-arg constructor to a Scala case class with a macro annotation?
- How can I write and read an empty case class with play-json?
- How can I apply a macro annotation to a case class with a context bound?
- How to create new instance of Scala class with context bound via Java reflection using only zero argument constructor?
- how to create scala case class with struct types?
- Scala syntax how to create an instance of a nested case class
- How can I parameterize a class with an object's type to get an instance of it in Scala?
- How would I get a list of constructor arguments for a case class in Scala?
- How to create Dataset with case class Type Parameter ? (Unable to find encoder for type T)
- How to create POJO class with only empty constructor in Scala?
- Scala - How to create a class with a constructor that receives an object as parameter
- How can I copy a case class with its trait?
- How to process future stream to create an instance of class with list property
- How can I implement a case class with several separate public interfaces?
- How to create a TestActorRef inside a test class for an Actor with constructor params?
- how to use repl to create instance of a case class defined in object
- How can I create multiple Datasets with different class types from one general Dataset?
- How to create a DataSet from RDD using Case Class with composed columns
- How can I map a case class with non-default field types to a table in Slick?
- How can I create A Class with Trait On Scala?
- Scala - How can we create class instance of same class?
- How to substitute objects in tree-like Scala case class instance with derived objects?
- How can we create case class object from json in scala + play framework 2.0
- Why I can create instance of case class in scala without new operator?
- How to clone a case class instance and change just one field in Scala?
More Query from same tag
- Scala Anonymous Function - does not behave as I expected
- play slick updating enumeration column
- Cannot Resolve Overloaded Method IntelliJ 2018.2.8 / Scala 2.11.8/Spark 2.4.5
- Comparing floating point numbers with tolerance fails assertion
- How to save the dataframe in scala as a csv ? csv function not working
- Replace all elements of a Seq from a String
- Mixing in a path dependent trait
- Specs2 running a matcher outside of the test class in an anonymous inner class
- How to get the output of groupby as below in spark scala
- How do I serialize an array of Objects into an array of Strings using GSON (with Scala)?
- Scala: map+filter instead of foldLeft
- Marshalling of `Map`s with Spray
- Is there a way to get an implicit manifest to a trait
- How to include per Project Jar file with xsbt-web-plugin / merge application.conf?
- Access methods of Generic which extents a trait
- Scala: unit-testing a method called asynchronously and returns a Future
- How to filter RDDs using count of keys in a map
- Cannot roll back session in auto-commit mode with Slick
- Mapping key values between different size vectors
- Time consuming write process of Spark Dataset into the Oracle DB using JDBC driver
- "Error:scalac: Error: object VolatileFloatRef does not have a member create" when using Scala 2.11.8 SDK
- How to convert DateTimeComparator to an Ordering[DateTime] in Scala
- No Json serializer as JsObject found for type play.api.libs.json.JsObject
- sbt/ivy version ranges does not resolve but exact versions do
- Attaching casbah source in eclipse
- When to use actors instead of messaging solutions such as WebSphere MQ or Tibco Rendezvous?
- How do I wait for an actor to stop during Play Framework shutdown?
- Prefetch SBT versions, Scala, and Ivy Resources with SBT for creating an image
- How to remove duplicated words in file using scala?
- Set console output color from a pattern in a xml with Logback