1

I need to create a function which is accepting two objects of same class. One is the updated object and other one is the old object. I need to find the differences in updated object by considering the old object. Like we have getDeclaredFields method in java to fetch all the variables.I am seeking for a way to get all the fields of an object and then i have to iterate one by one field and on the basis of its type i have to check equals on both the objects.

// code from comment included:

def trackChanges(newRecord:Object,oldRecord:Object) :String = { 
  val fields :Array[Field] = newRecord.getClass.getDeclaredFields 
  var check : String = "Equal" 
  for( i <- 0 to fields.length-1) { 
    fields(i).setAccessible(true) 
    val fieldType:Object = fields(i).getType 
    fieldType match { 
      case x: String => fields(i).get(newRecord).equals(fields(i).get(oldRecord)) 
      case x: java.lang.Double => println("String") 
      case x: Seq[] => println("String") 
      case x: List[] => }
user unknown
  • 35,537
  • 11
  • 75
  • 121
priyam singh
  • 105
  • 3
  • 16
  • Possible duplicate of [How to compare two objects for equality in Scala?](https://stackoverflow.com/questions/28426909/how-to-compare-two-objects-for-equality-in-scala) – airudah Feb 20 '18 at 10:18
  • No its not duplicate !! I want to use reflection API to get all the fields and types at runtime \ – priyam singh Feb 20 '18 at 10:44
  • def trackChanges(newRecord:Object,oldRecord:Object) :String = { val fields :Array[Field] = newRecord.getClass.getDeclaredFields var check : String = "Equal" for( i <- 0 to fields.length-1) { fields(i).setAccessible(true) val fieldType:Object= fields(i).getType fieldType match { case x: String=> fields(i).get(newRecord).equals(fields(i).get(oldRecord)) case x: java.lang.Double => println("String") case x: Seq[_] => println("String") case x: List[_] => } – priyam singh Feb 20 '18 at 11:26
  • Given two objects o1, o2. Shall trackChanges (o1, o2) lead to the same result, as trackChanges (o2, o1)? – user unknown Feb 20 '18 at 13:28

3 Answers3

0

So you've got some objects:

scala> trait MyTrait {
     | val x: String
     | val y: Int
     | }
defined trait MyTrait

scala> object MyObjectA extends MyTrait {
     | val x = "priyam"
     | val y = 1
     | }
defined object MyObjectA

scala> object MyObjectB extends MyTrait {
     | val x = "singh"
     | val y = 2
     | }
defined object MyObjectB

scala> object MyObjectC extends MyTrait {
     | val x = "priyam"
     | val y = 1
     | }
defined object MyObjectC

Since you can't compare two objects, you could create a case class from your object. That would give you a comparator for free:

scala> def createFromObject(obj: MyTrait): MyCaseClass = MyCaseClass(obj.x, obj.y)
createFromObject: (obj: MyTrait)MyCaseClass

And now, you compare the objects:

scala> createFromObject(MyObjectA) == createFromObject(MyObjectC)
res5: Boolean = true

scala> createFromObject(MyObjectA) == createFromObject(MyObjectB)
res6: Boolean = false

You can also call individual members from the original object or the case class:

scala> MyObjectA.x
res7: String = priyam

scala> createFromObject(MyObjectA).a
res8: String = priyam
airudah
  • 1,169
  • 12
  • 19
0

Idea 1. Do not use reflection at runtime. Reflection is heavy and slow mechanism, so using it for tracking changes in objects may kill all performance of your solution. I recommend you to write it directly, for each field, by hand. It would be fast.

if (obj1.field != obj2.field) {}

Idea 2. But I assume that you mean yourself as good programmer, and you worry about future code maintainance, and I assume you are to lazy to write it by hand. So. Because scala runs on JVM, java-reflection is also awailable here. you may use getDeclaredFields freely. If you want to use scala reflection, you may see here : https://github.com/yudnikov/transactions/blob/master/src/main/scala/ru/yudnikov/meta/describing/Reflector.scala - here are examples of scala reflection usage. Pay attention to

def getTerms(...)

and you'll need to understand what is runtime mirror...

Idea 3. The true programmers solution for this problem is to use scala macros with reflection at compile time to generate low-level lightweight code from Idea №1 automatically, during compilation. But I can't help you with this. Good luck ;)

Igor Yudnikov
  • 434
  • 1
  • 6
  • 14
-1
def trackChanges(newRecord:Object,oldRecord:Object) :String = {
    val fields :Array[Field] = newRecord.getClass.getDeclaredFields
     var check : String = "Equal"
   for( i <- 0 to fields.length-1)
   {
     fields(i).setAccessible(true)
    val fieldType:Object= fields(i).getType
    fieldType match
        {
          case x: String=> fields(i).get(newRecord).equals(fields(i).get(oldRecord))
          case x: java.lang.Double => println("String")
          case x: Seq[_] => println("String")
          case x: List[_] =>
        }
priyam singh
  • 105
  • 3
  • 16