如何通过混入反射来访问对象中的对象?

17 浏览
0 Comments

如何通过混入反射来访问对象中的对象?

如何使用反射获取对象中的所有对象?

考虑以下代码:

object MonthDay extends MyEnum {
  //一些重要的节日
  object NewYear       extends MonthDay( 1,  1)
  object UnityDay      extends MonthDay(11,  9)
  object SaintNicholas extends MonthDay(12,  6)
  object Christmas     extends MonthDay(12, 24)
}
class MonthDay(month: Int, day: Int)
trait MyEnum {
  val values: List[MonthDay] = this.getClass.getField("MODULE$")...
  val next: MonthDay = ...
  val previous: MonthDay = ...
}
//当然用户可以创建自己的MonthDay对象
val myBirthDay = new MonthDay(month, day)
if(!MonthDay.values.contains(myBirthDay)) "嗯,我可能得工作一下"
else "太好了,今天是个假日!"

我想要一个trait(MyEnum),可以将其混入持有我的"枚举对象"的对象中,以返回一个包含这些对象的列表(def values: List[MonthDay])或对它们进行迭代(def next: MonthDaydef previous: MonthDay),而不需要重复多次(这非常关键!)。

这个想法是,values通过反射访问MonthDay对象,并找到所有扩展该类(MonthDay)的单例对象。

0
0 Comments

问题出现的原因:

问题的提出者想要在Scala中使用反射来访问对象中的对象。他已经尝试使用Scala的预定义的Enumeration类,但发现它不能满足他的需求。

解决方法:

根据其他用户的建议,问题的提出者可以尝试使用Scala的Enumeration类来解决问题。Enumeration类可以作为一个枚举类型,允许用户定义一组可枚举的值。然而,由于Enumeration类是final的,无法被扩展,所以用户不能创建自己的MonthDays对象。

可能的解决方法是使用其他方式来实现用户所需的功能,例如使用trait来定义可枚举的值,并使用反射来访问这些值。通过混入这个trait,用户可以在对象中访问对象。

下面是一个可能的解决方案:

trait MonthDays {
  def days: Seq[String]
}
object January extends MonthDays {
  val days = Seq("1", "2", "3")
}
object February extends MonthDays {
  val days = Seq("4", "5", "6")
}
object Main extends App {
  val months = Seq(January, February)
  
  months.foreach { month =>
    println(month.days)
  }
}

在这个解决方案中,我们定义了一个MonthDays trait,它包含一个days方法,返回一个包含字符串的序列。然后我们创建了几个对象,分别混入MonthDays trait,并实现days方法。在Main对象中,我们创建了一个包含January和February对象的序列,并使用foreach方法遍历这个序列,打印每个对象的days值。

通过这种方式,我们可以使用反射来访问对象中的对象,同时也满足了用户的需求。

0
0 Comments

这篇文章讨论了如何通过反射将特质(trait)混入到对象中,以访问对象中的其他对象。在文章中,作者提出了一个基于Landei答案的解决方案。解决方案的代码如下所示:

trait MyEnum{
   def valsOfType[T:Manifest] = {
      val c=implicitly[Manifest[T]].erasure
      for {m <- getClass.getMethods 
           if m.getParameterTypes.isEmpty && c.isAssignableFrom(m.getReturnType)
      } yield (m.invoke(this).asInstanceOf[T])
   }
}
class MonthDay(month:Int,day:Int)
object MonthDay extends MyEnum {
   //maybe you want to call this "holidays" instead
   lazy val values = valsOfType[MonthDay] 
   val NewYear       = new MonthDay( 1,  1)
   val UnityDay      = new MonthDay(11,  9)
   val SaintNicholas = new MonthDay(12,  6)
   val Christmas     = new MonthDay(12, 24)
}

然后,作者指出这个解决方案不能处理枚举值被定义为对象的情况。作者提到了一个可能的解决方法,即使用getClass.getDeclaredClasses来获取对象中的其他对象,但目前这个方法还不可行。作者提供了一个bug报告链接,详细说明了问题:lampsvn.epfl.ch/trac/scala/ticket/4023

在讨论中,还有对MyEnum这个名称的建议,因为枚举类型暗示了一组封闭的值,而这个解决方案可以处理更灵活的情况。最后,作者提出了一个更长的名称trait FlexibleEnumeratedSubsetOfClassInstancesWithUsefulConvenienceMethods作为可能的替代名称。

整体而言,这篇文章讨论了通过反射将特质混入到对象中以访问对象中的其他对象的问题,并提供了一个解决方案和相关讨论。

0
0 Comments

问题的出现的原因是使用反射时无法访问对象内部的对象/字段/方法。解决方法是使用Java反射来查找返回指定类型的无参函数,并假设每个函数都是枚举值。这个方法可以排除使用def关键字声明的函数。同时,通过使用m.invoke()将找到的函数转换为枚举值。然而,这种方式在某些情况下无法正常工作,反射的功能不如预期。

0