The simple answer is yes (and you should not need to look beyond that for most practical purpose).
But the matter is more complicated than it looks; quoting The Unified Modeling Language Reference Manual, Second Edition:
The words generalization and
inheritance are often used interchangeably, but there are
actually two related but distinct
concepts. Generalization is a
taxonomic relationship among modeling
elements. It describes what an element
is. Inheritance is a mechanism for combining shared incremental
descriptions to form a full
description of an element. In most
object-oriented systems, inheritance
is based on generalization, but
inheritance can be based on other
concepts, such as the delegation
pointer of the Self language. Basing
the inheritance mechanism on the
generalization relationship enables
factoring and sharing of descriptions
and polymorphic behavior. This is the
approach taken by most object-oriented
languages and by UML. But keep in mind
that there are other approaches that
could have been taken and that are
used by some programming languages.
I remember a pretty long lecture, back in 2003, on the difference between generalization and inheritance. In short, these two concepts belong to different levels of software design, or quoting Martin Fowler in UML Distilled, Third Edition, "various perspectives of modeling":
Conceptually, we can say that a
Corporate Customer is a subtype of
Customer if all instances of Corporate
Customer are also, by definition,
instances of Customer. A Corporate
Customer is then a special kind of
Customer.
The concept of generalization belongs to the conceptual, design level.
But inheritance is a concept that belongs to the implementation perspective:
With a software perspective, the
obvious interpretation is inheritance:
The Corporate Customer is a subclass
of Customer. In mainstream OO
languages, the subclass inherits all
the features of the superclass and may
override any superclass methods.
I remember an example where the difference between generalization and inheritance really made sense:
A square is a rectangle. That comes from their definitions in mathematics:
- a rectangle is a quadrilateral with four right angles
- a square is a polygon with four equal sides and angles
At design level, there is a generalization relationship between the square and the rectangle.
But at the implementation level, things beg to differ:
- a rectangle can be defined by two measures: its width and height
- a square can be defined by a single measure, since all sides are equal
It would be counterproductive to inherit the width and height of the Rectangle class in the Square class, which would require extra constraints to ensure that the same value is provided to a setter for the width and a setter for the height.
This is a case (somewhat edgy I admit) where you would not translate a generalization relationship to the use of inheritance at the implementation level.
Well, those were the days.