tags:

views:

246

answers:

6

Hi gurus

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

+1  A: 

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!

egarcia
+1  A: 

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()

Don
Hi Don, thanks, but my collection is not empty.
Tom
A: 

Hi Egarcia,

thank for your help. I try your test. Method speak() return expected results.
For Man return "Man", for Woman return "Woman".
Your test finished ok, but my trouble is always here.

Maybe I forgot get more information:
This code is from Grails project. I mean that it is not important.
Exactly I use GORM call:

def humans = Human.findAll() 

Tomas

Tom
A: 

Hi gurus

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

Tom
A: 

Which version of Grails? I just tried this in the Grails 1.2.2 console and it works:

new Woman(name: "Julie").save()
new Woman(name: "Xena").save()
new Woman(name: "Mary").save()
new Man(name: "James").save()
new Man(name: "Tony").save(flush: true)

def people = Human.list()
for (p in people) {
    println ">> ${p.name} (${p.getClass()})"

    if (p instanceof Man) println "It's a man"
    if (p instanceof Woman) println "It's a woman"
}

Perhaps it's an issue that has been fixed?

Peter Ledbrook
Hi Peter, I use Grails 1.3.1.
Tom
See Tiggerizzy's answer for a solution in Grails 1.3.
Peter Ledbrook
+5  A: 

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

Tiggerizzy