从案例对象字段读取值,该字段使用反射扩展特征

时间:2016-10-24 12:35:20

标签: scala reflection enums

这可能是一个奇怪的问题,但我正在尝试一些事情,并坚持到这一步。

对于enumuerators,我使用的是sealed trait - case object方法。我正在尝试为每个注释生成一个Typescript类,以避免枚举的前端和后端值之间的不匹配。这是我的示例枚举实现。

sealed trait BankingTypeEnum {
  val id: Long
  val name: String
}

object BankingTypeEnum {

  case object Cheque extends BankingTypeEnum {
    override val id: Long = 1
    override val name: String = "Loan"
  }

  case object Current extends BankingTypeEnum {
    override val id: Long = 2
    override val name: String = "Current"
  }

  case object Savings extends BankingTypeEnum {
    override val id: Long = 3
    override val name: String = "Savings"
  }

}

我想要做的是将值放入一个简单的case类中,以后可以用它来生成typescript文件。但是,我不确定如何使用反射在生成时获取字段值。如果我使用case类而不是case对象,我可以使用反射创建类的实例,但我不想这样做。还有其他方法,我可以获取案例对象枚举的值idname字段吗?

2 个答案:

答案 0 :(得分:0)

这不是最好的解决方案,因为你有点嘲笑scala Enumerations http://underscore.io/blog/posts/2014/09/03/enumerations.html

但是关于你的方法,你可以添加一个Set。此外,我已将特征放入对象中:

object BankingTypeEnum {
  sealed trait BankingType {
    val id: Long
    val name: String
  }

  val bankingTypes: Set[BankingType] = Set(Cheque, Current, Savings)

  case object Cheque extends BankingType{
    override val id = 1L
    override val name = "Loan"
  }
  case object Current extends BankingType{
    override val id = 2L
    override val name = "Current"
  }
  case object Savings extends BankingType{
    override val id = 3L
    override val name = "Savings"
  }
}

然后你可以生成一个像:

这样的const
BankingTypeEnum.bankingTypes.foldLeft("export const BankingTypes = {")((a,b) => {
  if(a != "export const BankingTypes = {")
    a + ",\""+b.name+"\":"+"{\"id\":"+b.id+",\"name\":\""+b.name+"\""+"}"
  else
  a + "\""+b.name+"\":"+"{\"id\":"+b.id+",\"name\":\""+b.name+"\""+"}"
}) + "}";

这会产生你:

export const BankingTypes = {"Loan":{"id":1,"name":"Loan"},"Current":{"id":2,"name":"Current"},"Savings":{"id":3,"name":"Savings"}}

Set(您可以使用List或其他)就是您不需要使用反射....

答案 1 :(得分:0)

好吧我以为你想省略反思。但如果没有(您可以使用此帖子中的代码):

val enums = for {
  f <- BankingTypeEnum.getClass.getDeclaredClasses
  c = f.getConstructors()(0)
  i = c.newInstance(BankingTypeEnum)
} yield (f.getMethod("id").invoke(i), f.getMethod("name").invoke(i))

这是相应的生成部分(它与我之前的答案相同):

enums.foldLeft("export const BankingTypes = {")((a,b) => {
  if(a != "export const BankingTypes = {")
    a + ",\""+b._2+"\":"+"{\"id\":"+b._1+",\"name\":\""+b._2+"\""+"}"
  else
    a + "\""+b._2+"\":"+"{\"id\":"+b._1+",\"name\":\""+b._2+"\""+"}"
}) + "}";

发生了什么事?首先在BankingTypeEnum中获取DeclaredClasses。下一步是让构造函数在第一个构造函数中更具体(没有&#34;对象&#34;在JVM中的scala中提供)。现在,您从构造函数创建实例,并将id和name作为元组返回给每个&#34; case对象&#34;通过调用方法。

您可以搜索有关scala字节代码的文章,因为如前所述,没有&#34; case类&#34;或&#34;对象&#34;在Java / JVM中。它们被构造为类和接口。 同样的vals。例如

 val id:Long = 4L

将(与Java类似)

private long id = 4L; 
public long id() = { return this.id }

因此,我调用了方法name()和id(),因为属性name和id是私有的。