theMadKing
theMadKing

Reputation: 2074

Scala calling a Object from a variable name

I have a few objects created with a function called .clean in each one:

HiveCleanerTbl
HiveCleanerDb

These Objects need to be called dynamically based on a record based on an API call being made that will let my Job know what object to call for instance I have it hard coded right now:

def matchSchema(schema:Int): Any = schema match {
          case 1 =>  HiveCleanerTbl.clean(rawRecord)
          case 32 => HiveCleanerDb.clean(rawRecord)
...

Earlier in the code instead of hardcoding the possible Objects is there a way to dynamically have the object populated like:

val systems = List[(String, String, Int)] = List((hiveTbl,HiveTblCleaner,6), (hiveDb,HiveDbCleaner,7))

And I have code that looks like this:

systems.foreach(x => if(x._1 == systemName) {
              cleanObject =  x._2
            })

How will I make the cleanObject defined as the object I want to use that can call its .clean function?

Upvotes: 0

Views: 522

Answers (2)

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

Yes, you can do that.

val systems = List[(Cleanable, String, Int)] = List((hiveTbl,HiveTblCleaner,6), (hiveDb,HiveDbCleaner,7))

Lets say your hiveTbl and hiveDb are cleanable and lets say clean method is available on them to invoke.

systems.foreach { 
  case (db: Cleanable, "cleanSchemeName", _) => 
   db.clean 
  case _ => () //ignore
}

If db does not have clean method then check the type of db and try pattern matching to resolve the real type of the db object.

Here is a general example how you can achieve this.

Cleanable gives clean method to A and B. List contains all cleanables so I can go ahead calling clean on each object without type casting the object.

Based on certain condition you can ignore clean some objects.

trait Cleanable {
  def clean(): Unit
}

case class A(a: Int) extends Cleanable {
  override def clean(): Unit = println("cleaned A")
}

case class B(a: Int) extends Cleanable {
  override def clean(): Unit = println("cleaned B")
}

val cleanableStuff: List[(String, Cleanable)] = List(("clean", A(10)), ("donot_clean", B(10)))

def cleanAll(list: List[(String, Cleanable)]): Unit = {
  list.foreach {
    case ("donot_clean", v) => //Ignore 1st object
    case (_, v) => v.clean() //clean other objects 
  }
}

Upvotes: 1

radumanolescu
radumanolescu

Reputation: 4161

All your objects seem to be "cleaners" - so create a trait called CanClean that defines the method clean(rawRecord: SomeType) and a property val schema: Int. The schema will be populated in each object with the appropriate value. Then put all these cleaners in a Map[Int, CanClean] with key: schema and value: object: CanClean. Then you can do cleanerMap(schema).clean(rawRecord). If you do not want to populate the cleanerMap by hand, you can use reflection to make a list of "all objects that implement CanClean".

Upvotes: 1

Related Questions