While is-a and has-a are the two major categories of abstraction used in object-oriented programs, they are certainly not the only types. We will examine just a few of the other ways abstraction finds application in programming.
One special type of has-a goes by the general name of composition. Like regular has-a abstraction, composition starts with some existing primitive forms, and rules for combining old values to create new abstractions. The key additional step is then that these rules can recursivly be applied to both the initial primitive forms, and to the new abstractions. In this recursive fashion extremely complex structures can be created step by step.
Examples of composition include regular experessions, type systems, windows, and lots of other complex systems.