Q:

What is a good way to specify multiple types of an object?

In object-oriented programming paradigm, as far as I know(I'm also an amateur at that :-) ), one often defined some classes, say Dogs and Cats, and declare some objects as those types, say Dogs Cody, Cats Lucy. And one may define a function shout() with respect to the classes Dogs and Cats to get the sound when that animal shout. Then he or she may evaluate Cody.shout() and get the string "Growl!", while Lucy.shout() gets "Meow~~".
Back to Mathematica, I found some article here said that types are corresponding to the Head in Mathematica. For example, such things may be implemented as
shout[x_Dogs] := "Growl!"
shout[x_Cats] := "Meow~~"
shout[Dogs[Cody]](*Cody is a dog, which is  indicated by its head*)
shout[Cats[Lucy]]
shout[Birds[Lilly]] (*we don't know how it shouts*)

and the output is 
"Growl!"
"Meow~~"
shout[Birds[Lilly]]

The first question, is it a good way to implement like this? Is this paradigm proper and wise enough?
The second question, is using a Head to indicate what the type of the object is, limited or not flexible? Since an object can have(belongs to) multiple types at the same time. For example, if x is a person, then he may have several nationalities(suppose it is legal :)), such as American and Chinese. Then, if we use
American[x]

To indicate the "type" of this person is American, we can't specify that he is also Chinese, since using Chinese[x] would be two different objects. Hence, I wonder if Head is a good way to implement such idea? Or can it be slightly modified and get what we want? Hmm.. I roughly come up with four idea.
One:
Using a list as "multiple heads", such like {Chinese, American}[x]
Two:
To define a concrete "type" function to deal with this things, such as
Type[x]={American,Chinese}

Three:
Elements[x,American](Not sure the right usage of Elements. Can user define their own domain?)
Four:
Use a predicate to indicate these relationship.
IsAmerican[x]=True
IsChinese[x]=True

Which is/are proper or good, or none of?

A:

You have made a good observation about how patterns can be used to implement paradigms which are reminiscent of object-oriented programming. You can do a lot of things with patterns, you're not limited to just looking at the head:
animals = {Animal["Dog", "Cody"], Animal["Cat", "Lucy"]};
shout[Animal["Dog", _]] := "Growl"
shout[Animal["Cat", _]] := "Meow"

shout /@ animals

{"Growl", "Meow"}

You can also get "properties" easily:
name[Animal[_, name_]] := name
name /@ animals

{"Cody", "Lucy"}

It can be even more general by using conditions:
people = {
   Person["Gustav", {"Swedish"}],
   Person["Cody", {"American", "Chinese"}],
   Person["John", {"Swedish", "American"}]
   };

greeting[Person[_, citizenship_]] /; 
  ContainsOnly[citizenship, {"Swedish"}] := "Hej"
greeting[Person[_, citizenship_]] /; 
  ContainsAny[citizenship, {"Chinese", "Vietnamese"}] := "Howdy"
greeting[Person[_, citizenship_]] /; 
  ContainsAll[citizenship, {"Swedish", "American"}] := "Hi"

{"Hej", "Howdy", "Hi"}

