# 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?

• May 14 '17 at 16:10

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"}

• Thanks! I see. By the way, I'm not a fan of OOP, actually I'm inexperienced in it. But I'm a fan in MMA paradigm. :) So I ask this question not because I want to mimic something in the OOP paradigm in Mathematica, but because I "guess" when organizing a big project, we inevitably or naturally need such "type"-like abstraction, and I wonder how to do it. So may I further ask that is it common for Mathematica programmers to so? Or do people actually use another abstraction(paradigm)? :)
– Eric
May 14 '17 at 16:24
• @Eric There are some who have attempted to implement object-oriented programming paradigms in Mathematica. But this is not like that, what I describe in this answer uses Mathematica's strengths very well and is a common technique in the Mathematica community. It's related to "destructuring", which you can read more about here. I don't think this paradigm in itself has a name, it just is what it is because of how the language is designed. May 14 '17 at 16:33