Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

instanceof in Grails

Tags:

grails

How to determine Class type of Object in collection?

class Human{...}
class Man extends Human{...}
class Women extends Human{...}

def humans = Human.findAll() 
humans.each(){ human ->

    // ??? , it is not work
   if ( human instanceof Man ) { println "Man" }
   if ( human instanceof Woman ) { println "Woman" }
}

Thanks a lot,
Tom

like image 596
Tomáš Avatar asked Jun 03 '10 10:06

Tomáš


4 Answers

Based on your description, I would say you are running into Hibernate proxy objects (ie. class name is: Human_$$javaassist*). Solution would be to use the GORM provided version of insatnceOf. No need to eager fetch or use a different method.

def planet = Planet.get(1)
planet.humans.each(){ human ->
    if (human.instanceOf(Man)) { println "is Man"}
    if (human.instanceOf(Woman)) { println "is Woman"}
}

Notice the difference human.instanceOf(Man) rather than human instanceof Man. Use the gorm method rather than the java keyword.

You can see this section of the reference documentation for an [explanation][1]. See subsection "Lazy Single-Ended Associations and Proxies"

[1]: http://grails.org/doc/latest/guide/single.html#5.5.2.8 Eager and Lazy Fetching

like image 117
Ben Doerr Avatar answered Nov 17 '22 13:11

Ben Doerr


It looks as if it should work.

A couple random thoughts: are your humans correctly built? Maybe they are really not instances of Man or Woman.

You can do some tests using polymorphism:

class Human{ ...
  def speak() { println "Human" }
}
class Man extends Human{ ...
  def speak() { println "Man" }
}
class Women extends Human{ ...
  def speak() { println "Woman" }
}
def humans = humanService.all()
humans.each(){ human ->
  human.speak()
}

If the last line prints "Human Human Human", then the humans are not correctly built, and they are all human instances, instead of Man / Woman. If it shows an error, then they are something else (like nulls or something)

Good luck!

like image 35
kikito Avatar answered Nov 17 '22 13:11

kikito


There's nothing wrong with the code above, so my guess is that Human.findAll() is returning an empty collection, which would explain why nothing is being printed. Can you try this code instead?

class Human{...}
class Man extends Human{...}
class Women extends Human{...}

println "You have ${Human.findAll().size()} humans"

If this prints "You have 0 humans", then my guess is correct. If you want to get a list of all instances of Human, then it's probably better to use Human.list() instead of Human.findAll()

like image 39
Dónal Avatar answered Nov 17 '22 12:11

Dónal


in Grails with Hibernate is really problem with instanceof. I have again trouble with it. I find this article:

http://community.jboss.org/wiki/ProxyVisitorPattern

I mean that trouble is appear when your class has some relations. For example:

def planet = Planet.get(1)
planet.humans.each(){ human ->

   //it is not work, see the link above
   if (human instanceof Man) { println "is Man"}
   if (human instanceof Woman) { println "is Woman"}
}

Tom

like image 1
Tomáš Avatar answered Nov 17 '22 12:11

Tomáš