Microlink IT and Business College
Postgraduate Studies
Department of MIS
1
Chapter 6-Relationships between
Objects
Compiled By: Solomon H. (Asst.
Prof.)
Associations and Links
2
Association
is the formal name for a structural
relationship that exists between classes.
With respect to the SRS, some sample
associations might be as follows:
A Student is enrolled in a Course.
A Professor teaches a Course.
A DegreeProgram requires a Course.
Associations and Links…
3
link
is a structural relationship that exists between
two specific objects (instances).
is an actual relationship between objects of
those particular types.
Given the association “a Student is enrolled in
a Course,” we might have the following links:
Chloe Shylow (a particular Student object) is enrolled
in Math 101 (a particular Course object).
Associations and Links…
4
A link may be conceptually thought of as a
specific instance of an association with its
participating objects filled in:
Example:
Associations and Links…
5
Binary Association
Interrelated two different classes-Student and Course
Unary/reflexive Association:
Is between two instances of the same class
Example
A Course is a prerequisite for (another)
Course(s).
A Professor supervises (other) Professor(s).
Associations and Links…
6
Even though the two classes specified at
either end of a reflexive association are the
same, the objects are typically different
instances of that class:
Math 101 (a Course object) is a prerequisite for Math
202 (a different Course object).
Professor Smith (a Professor object) supervises
Professors Jones and Green (other Professor objects).
Associations and Links…
7
Ternary Association We typically decompose
involves three classes— higher-order associations into
an appropriate number of
E.g., “a Student takes a binary associations.
Course from a particular Example:
Professor” A Student attends a Course.
Example:
A Professor teaches a Course.
A Professor instructs a Student.
Associations and Links…
8
Within a given association, each participant
class is said to have a role.
In the advises association (“a Professor advises a
Student”), the role of the Professor might be said to be
“advisor,” and the role of the Student might be said to
be “advisee.”
Multiplicity
9
For a given association type X between
classes A and B, multiplicity refers to the
number of objects of type A that may be
associated with a given instance of type B.
Example:
a Student attends multiple Courses, but
a Student has only one Professor in the role of advisor.
There are three basic “flavors” of multiplicity:
one-to-one,
one-to-many, and
many-to-many.
One-to-One (1:1)
10
Exactly one instance of class A is related to
exactly one instance of class B, and vice
versa.
Example:
A Student has exactly one Transcript, and a Transcript
belongs to exactly one Student.
A Professor chairs exactly one Department, and a
Department has exactly one Professor in the role of
chairperson.
One-to-One (1:1)…
11
We can further constrain an association by
stating whether the participation of the class
at either end is optional or mandatory.
Example:
A Professor optionally chairs exactly one Department,
but it is mandatory that a Department has exactly
one Professor in the role of chairperson.
If a professor happens to be a chairperson of a
department, then that professor is the chairperson of
only one department.
One-to-Many (1:m)
12
There can be many instances of class B
related to a single instance of class A in a
particular fashion; but, from the perspective of
an instance of class B, there can only be one
instance of class A that is so related.
Example:
A Department employs many Professors, but a
Professor works for exactly one Department.
A Professor advises many Students, but a given
Student has exactly one Professor as an advisor.
One-to-Many (1:m)…
13
“many”-can be interpreted as either “zero or
more (optional)” or as “one or more
(mandatory).”
Example:
A Department employs one or more (“many”;
mandatory) Professors, but a Professor works for
exactly one Department.
A Professor advises zero or more (“many”; optional)
Students, but a given Student has exactly one
Professor as an advisor.
One-to-Many (1:m)…
14
The “one” end of a 1:M association may also
be designated as mandatory or as optional.
Example:
A Professor advises zero or more (“many”; optional)
Students, but a given Student may optionally have at
most one (i.e., zero or one) Professor as an advisor.
Many-to-Many (m:m)
15
A given single instance of class A can have
many instances of class B related to it, and
vice versa.
Example:
A Student enrolls in many Courses, and a Course has
many Students enrolled in it.
A given Course can have many prerequisite Courses,
and a given Course can in turn be a prerequisite for
many other Courses. (This is an example of a M:M
reflexive association.)
Many-to-Many (m:m)
16
“Many” can be interpreted as zero or more
(optional) or as one or more (mandatory) at
either end of an (M:M) association.
Example:
A Student enrolls in zero or more (“many”; optional)
Courses, and a Course has one or more (“many”;
mandatory) Students enrolled in it.
Multiplicity and Links
17
Multiplicity pertains to associations, but not to links.
Links always exist in pairwise fashion between two
objects (or, in rare cases between an object and itself ).
Multiplicity defines how many links of a certain
association type can originate from a given object.
Example:
Consider the M:M is enrolled in association:
A Student enrolls in zero or more Courses, and a Course has one or
more Students enrolled in it.
A specific Student object can have zero, one, or more
links to Course objects, but any one of those links is
between exactly two objects: a single Student object and
a single Course object.
Multiplicity and Links…
18
Example: Example 2: 1:1 association
Student X has one link (to Course A). A Professor optionally chairs exactly
Student Y has four links (to Courses A, one Department, and it is mandatory
B, C, and D). that a Department has exactly one
Professor in the role of chairperson.
Student Z has no links to any Course
Professor objects 1 and 4 each have one
objects whatsoever. (Z is taking the link, to Department objects A and B,
semester off!) respectively.
Professor objects 2 and 3 have no such
links.
Inheritance
19
While encapsulation and information hiding
are arguably achievable with non-OO
languages in some form or another, the
inheritance mechanism is what truly sets OO
languages apart from their non-OO
counterparts.
Responding to Shifting Requirements with a
New Abstraction
20
Assume we’ve accurately
and thoroughly modeled
all of the essential
features of students via
our Student class.
A simplified version of
the Student class is as
follows:
Assume:
The below Student class
has been rigorously
tested, found to be bug
free, and is actually being
used in a number of
applications:
Responding to Shifting Requirements with a
New Abstraction…
21
A new requirement has just arisen for modeling graduate
students as a special type of student.
The only information about a graduate student that we
need to track above and beyond that which we’ve
already modeled for a “generic” student is
What undergraduate degree the student previously received before
entering his or her graduate program of study
What institution the student received the undergraduate degree
from
All of the other features(attributes and their
corresponding accessor methods) necessary to describe
a graduate student—are the same as those that we’ve
already programmed for the Student class, because a
graduate student is a student.
Responding to Shifting Requirements with a
New Abstraction…
22
If we weren’t well versed in OO concepts, we
might try one of the following approaches to
this new requirement.
(Inappropriate) Approach #1:Modify the Student
Class
23
We could add attributes to our existing Student class to reflect
undergraduate degree information, along with “get”/“set” methods for these
new attributes, as follows:
We've added two attributes to Student to handle the new requirements for graduate
students
We've also added four accessor methods.
(Inappropriate) Approach #1:Modify the Student
Class…
24
We'll set this next attribute to true if this is a graduate student,
false otherwise.
(Inappropriate) Approach #1:Modify the Student
Class…
25
If a particular student is NOT a
graduate student, then the values
of the attributes
"undergraduateDegree" and
"undergraduateInstitution“ would
be undefined/irrelevant, and so
we only want to print them if we
are dealing with a GRADUATE
student.
(Inappropriate) Approach #1:Modify the Student
Class…
26
Very difficult to debug!
Example:
consider how complicated the display method
would become if we wanted to use it to represent a
third type of student: namely, continuing education
students, who don’t seek a degree, but rather are
just taking courses for continuing professional
enrichment.
Perhaps for such students, we’d like to track their current
place of employment as an attribute.
We’d most likely need to add yet another boolean flag as an
attribute, as well, to keep track of whether or not a particular
Student is a continuing education student.
(Inappropriate) Approach #1:Modify the Student
Class…
27
(Inappropriate) Approach #1:Modify the Student
Class…
28
The display method
will also be modified
to include the if
statement for
continuing education
(Inappropriate) Approach #1:Modify the Student
Class…
29
Imagine how much more “spaghetti-like” our
code might become if we had dozens of
different student types to accommodate.
Approach #1 is clearly not the answer!
we’re trying too hard to force a single abstraction,
Student, to represent multiple real-world object types.
While graduate students, continuing
education students, and “generic” students
certainly have some features in common, they
are nonetheless different types of object.
(Inappropriate) Approach #2: “Clone” the Student
Class to
Create a GraduateStudent Class
30
We could instead create a new
GraduateStudent class by copying the code
of [Link] to create
[Link], renaming the latter
class GraduateStudent, and then adding the
extra features required of a graduate student
to the copy.
(Inappropriate) Approach #2: “Clone” the Student
Class to
Create a GraduateStudent Class…
31
(Inappropriate) Approach #2: “Clone” the Student
Class to
Create a GraduateStudent Class…
32
This would be a very poor design, since we’d have
much of the same code in two places:
If we wanted to change how a particular method worked or how
an attribute was defined later on—say, a change of the type of
the birthDate attribute from String to Date, with a corresponding
change to the accessor methods for that attribute—then we’d
have to make the same changes in both classes.
This problem quickly gets compounded if we’ve
defined three, or four, or a dozen different types of
Student, all created as “clones” of the original
Student class; the code maintenance burden would
quickly become excessive.
Approach #2 is clearly not the answer, either!
The Proper Approach (#3):Taking Advantage
of Inheritance
33
With an OOPL, we can solve the problem of specializing the
Student class by harnessing the power of inheritance-a
mechanism for defining a new class by stating only the
differences (in terms of features) between the new class
and another class that we’ve already established.
Using inheritance, we can declare a new class name
GraduateStudent that inherits all of the features of the
Student class “as is.”
The GraduateStudent class would then only have to specify the two
extra attributes associated with a graduate student—
undergraduateDegree and undergraduateInstitution—plus their
accessor methods
Inheritance is triggered in using the extends keyword:
public class NewClass extends ExistingClass { ... .
The Proper Approach (#3):Taking Advantage
of Inheritance…
34
The Proper Approach (#3):Taking Advantage
of Inheritance…
35
It’s as if we had “plagiarized” the code for the attributes and
methods of the Student class, copying this code from
Student and pasting it into GraduateStudent, but without the
fuss of actually having done so.
The GraduateStudent class thus has n + 6 features: the six
features that are explicitly declared within the
[Link] file plus n more that are inherited
from Student.
When we take advantage of inheritance, the original class
that we’re starting from—Student, in this case—is called the
(direct) superclass.
The new class—GraduateStudent—is called a (direct)
subclass.
A subclass is said to extend its direct superclass.
The “is a” Nature of Inheritance
36
Inheritance is referred to as the “is a” relationship
between two classes, because if a class B is derived
from a class A, then B truly is a special case of A.
Anything that we can say about a superclass must
therefore also be true about all of its subclasses; i.e,
A Student attends classes, and so a GraduateStudent attends
classes.
A Student has an advisor, and so a GraduateStudent has an advisor.
An “ACID test” for legitimate use of inheritance is as
follows:
if there is something that can be said about a class A
that can’t be said about a proposed subclass B, then B
really isn’t a valid subclass of A.
The “is a” Nature of Inheritance…
37
Specialization
refers to the process of deriving one class from another.
Generalization
recognizing the common features of several existing classes and
creating a new, common superclass for them all.
Students and Professors have some features in common:
attributes name, birthDate, etc., and the methods that
manipulate these attributes. Yet, they each have unique
features, as well:
The Professor class might require the attributes title (a String) and worksFor
(a reference to a Department).
The Student class’s studentID, degreeSought, and majorField attributes are
irrelevant for a Professor.
The “is a” Nature of Inheritance…
38
Because each class has attributes that the
other would find useless, neither class can be
derived from the other.
to duplicate their common attribute declarations and
method code in two places would be very inefficient.
we’d want to invent a new superclass called Person,
consolidate the features common to both Students and
Professors in the Person class, and then have Student
and Professor inherit these common features by
extending Person.
The “is a” Nature of Inheritance…
39
Attributes common to Attributes specific only to a
Students and Professors. Student;
redundant attributes - i.e.,
Common accessor
those that are shared with
methods. Professor, and hence are now
Other general-purpose Person declared by Person – have
methods, if any, would go here been REMOVED from Student.
- details omitted. Student-specific accessor
methods - redundant methods
have been removed.
The “is a” Nature of Inheritance…
40
Attributes specific only to a
Professor;
redundant attributes - i.e.,
those that are shared with
Student, and hence are now
declared by Person – are not
included here.
Professor-specific accessor-
methods go here.
Other Professor-specific
methods go here, if any;
The Benefits of Inheritance
41
Inheritance is one of the most powerful and
unique aspects of an OOPL for the following
reasons:
We dramatically reduce code redundancy-
lessening the burden of code maintenance when
requirements change or logic flaws are detected.
Subclasses are much more succinct than they
would be without inheritance. A subclass contains
only the essence of what differentiates it from its direct
superclass.
The Benefits of Inheritance…
42
Through inheritance, we can reuse and extend
code that has already been thoroughly tested
without modifying it.
Best of all, we can derive a new class from an
existing class even if we don’t own the source code
for the latter!
As long as we have the compiled bytecode version
of a class, the inheritance mechanism works just fine;
we don’t need the original source code of a class in
order to extend it. This is one of the most dramatic
ways to achieve productivity with an OO
language:
Class Hierarchies
43
Is an inverted tree of
classes that are
interrelated through
inheritance.
Arrows are used to
point upward from
each subclass to its
direct superclass.
Class Hierarchies…
44
Node
Refers to each class in the hierarchy.
Any given node in the hierarchy is said to be (directly or
indirectly) derived from all of the nodes above it in the
hierarchy, known collectively as its ancestors.
The ancestor that is immediately above a given node in
the hierarchy is considered to be that node’s direct
superclass.
All nodes below a given node in the hierarchy are said to be its
descendants.
Root node
The node that sits at the top of the hierarchy.
Terminal/leaf/node,
is one that has no descendants.
Class Hierarchies…
45
Siblings
Two nodes that are derived from the same direct
superclass.
Class A (Person) is the root node of the entire hierarchy.
Classes B, C, D, E, and F are all said to be derived from
class A, and thus are all descendants of A.
Classes D, E, and F can be said to be derived from class
B.
Classes D, E, and F are siblings; so are classes B and C.
Class D has two ancestors, B (its direct superclass) and
A.
Classes C, D, E, and F are terminal nodes, in that they
don’t have any classes derived from them (as of yet, at
any rate).
As with any hierarchy, this one may evolve over time:
It may widen with the addition of new
siblings/branches in the tree.
It may expand downward as a result of future
specialization.
It may expand upward as a result of future
generalization.
Class Hierarchies…
46
Such changes to the hierarchy are made as
new requirements emerge, or as our
understanding of the existing requirements
improves.
Example:
we may determine the need for
MastersStudent and PhDStudent classes as
specializations of GraduateStudent, or of an
Administrator class as a sibling to Student and
Professor.
Class Hierarchies…
47
The Object Class
48
The built-in Object class serves as the ultimate superclass
for all other reference types, both user-defined and those
built into the language.
Even when a class is not explicitly declared to extend
Object, such extension is implied.
Example:
public class Person { ... }
it is as if we’ve written
public class Person extends Object { ... }
without having to explicitly do so. And, when we write
public class Student extends Person { ... }
then, because the Person class is derived from Object,
Student is derived from Object as well.
Is Inheritance Really a
Relationship?
49
Association, aggregation, and inheritance are all
said to be relationships between classes.
Inheritance differs from association and
aggregation at the object level.
Association (and aggregation, as a special form of
association) can be said to relate individual
objects, in the sense that two different objects are
linked to one another by virtue of the existence of
an association between their respective classes.
Is Inheritance Really a
Relationship?...
50
Inheritance does not involve linking distinct
objects; rather, inheritance is a way of
describing the collective features of a single
object.
With inheritance, an object is
simultaneously an instance of a subclass
and all of its superclasses: a GraduateStudent
is a Student that is a Person that is an Object,
all wrapped into one!
Is Inheritance Really a
Relationship?...
51
All classes in the hierarchy—class A (Person) as well as
all of its descendants B through I—may be thought of
as yielding Person objects.
Class B (Student), along with its descendants D
through H, may all be thought of as yielding Student
objects.
This notion of an object having “multiple
identities” is a significant one.
Inheritance is a relationship between classes,
but not between distinct objects.
Avoiding “Ripple Effects” in a Class Hierarchy
52
Once a class hierarchy is established and an
application has been coded, changes to non-
leaf classes (i.e., those classes that have
descendants) have the potential to introduce
undesired ripple effects further down the
hierarchy.
Whenever possible, avoid adding features to non-leaf
classes once they have been established in code form
in an application, to avoid ripple effects throughout an
inheritance hierarchy.
Rules for Deriving Classes: The
“Do’s”
53
When deriving a new class, we can do several
things to specialize the superclass that we are
starting out with.
We may extend the superclass by adding features.
In the GraduateStudent example, we added six
features: two attributes—and four accessor methods.
We also may specialize the way that a subclass
performs one or more of the services inherited from
its superclass.
Rules for Deriving Classes: The “Do’s”…
54
Example:
when a “generic” student enrolls for a course, the business rules
for the SRS may require us to ensure that
The student has taken the necessary prerequisite courses.
The course is required for the degree that the student is seeking.
When a graduate student enrolls for a course, the business
rules may involve doing both of these things as well as ensuring
that the student’s graduate committee feels that the course is
appropriate.
Specializing the way that a subclass performs a service—that is,
how it responds to a given message as compared with the way
that its superclass would have responded to the same message
— is accomplished via a technique called overriding.
Overriding
55
involves “rewiring” how a method works
internally, without changing the client code
interface to/signature of that method.
Example:
let’s say that we’ve defined a print method for
the Student class to print out the values of all
of a Student’s attributes:
Overriding…
56
Print the values of all of the
attributes that the Student
class knows about.
Remember: "\n" is a newline.
Overriding…
57
With an OO language, we are able to
override, or supersede, the superclass’s
version of a method with a subclass-specific
version.
To override a superclass’s method rather than
merely inheriting the method as is, the header
of the method as declared in the superclass
must be repeated in the subclass; we are then
free to reprogram the body of that method in
the subclass to specialize its behavior.
Overriding…
58
We are overriding the Student
class's print method; note that
we've repeated the print method
header verbatim from the Student
class, which triggers overriding.
We print the values of all of the
attributes that the
GraduateStudent class knows
about: namely, those that it
inherited from Student plus those
that it explicitly declares above.
Overriding…
59
The GraduateStudent class’s version of print thus overrides, or
supersedes, the version that would otherwise have been
inherited from the Student class.
In a complex inheritance hierarchy, we often have occasion to
override a given method multiple times.
Root class A (Person) declares a method with the header public void
print() that prints out all of the attributes declared for the Person class.
Subclass B (Student) overrides this method, changing the internal logic of
the method body to print not only the attributes inherited from Person,
but also those that were added by the Student class itself.
Subclass E (GraduateStudent) overrides this method again, to print not
only the attributes inherited from Student (which include those inherited
from Person), but also those that were added by the GraduateStudent
class itself.
In all cases, the method signature must remain the same—
print()—for overriding to take place.
Overriding…
60
Any class not specifically
overriding a given
method itself will inherit
the definition of that
method used by its most
immediate ancestor.
Thus,
Classes C and D in Figure
below inherit the versions of
print() that are defined by A
and B, respectively.
F is therefore overriding the
print() method of A as
inherited by C.
Reusing Superclass Behaviors:
The “super” Keyword
61
The Student version of The GraduateStudent
the print method: version of the print
version:
Reusing Superclass Behaviors:
The “super” Keyword…
62
Redundancy in an application is to be avoided
whenever possible, because redundant code
represents a maintenance headache.
When we have to change code in one place in an
application, we don’t want to have to remember to
change it in countless other places or, worse yet,
forget to do so, and wind up with inconsistency in our
logic.
Java provides a way for us to have our cake and eat it too—i.e., a
way for us to override the print method while simultaneously
reusing its code.
Reusing Superclass Behaviors:
The “super” Keyword…
63
Reuse code by calling
the print method as
defined by the Student
superclass ...
Reusing Superclass Behaviors:
The “super” Keyword…
64
We use the super keyword as the qualifier for a
method call:
[Link](arguments);
whenever we wish to invoke the version of method
methodName that was defined by our superclass.
we’re saying to the compiler, “First, execute the print method
the way that the superclass, Student, would have executed
it, and then do something extra—namely, print out the
values of the new GraduateStudent attributes.”
The syntax
[Link](arguments);
involves invoking one method from within another.
Reusing Superclass Behaviors:
The “super” Keyword…
65
public class Superclass {
public void foo(int x, int y) { ... }
}
public class Subclass extends Superclass {
// We're overriding the foo method.
// (Note that we're using a and b as parameter names here to
override
// parameters x and y in the superclass; this is perfectly fine as
long
// as their types are identical.)
public void foo(int a, int b) {
// Details to follow ...
}
}
Reusing Superclass Behaviors:
The “super” Keyword…
66
public class Subclass extends Superclass {
// We're overriding the foo method.
public void foo(int a, int b) {
// We can pass the argument values a and b through to our
superclass's
// version of foo ...
[Link](a, b);
}
}
or
Reusing Superclass Behaviors:
The “super” Keyword…
67
public class Subclass extends Superclass {
// We're overriding the foo method.
public void foo(int a, int b) {
int x = 2; // a local variable
// We can pass selected argument values through to our superclass's
// version of foo ...
[Link](a, x);
}
}
or even
public class Subclass extends Superclass {
// We're overriding the foo method.
public void foo(int a, int b) {
int x = 2; // a local variable
// Here, we're using neither a nor b as an argument.
[Link](x, 3);
}
}
Reusing Superclass Behaviors:
The “super” Keyword…
68
Note that our invocation of [Link](...) can
occur anywhere within the method:
public class Subclass extends Superclass {
// We're overriding the foo method.
public void foo(int a, int b) {
// Pseudocode.
do some stuff;
[Link](a, b);
// Pseudocode.
do more stuff;
}
}
Reusing Superclass Behaviors:
The “super” Keyword…
69
And, if foo were declared to have a non-void return
type in Superclass—say, int—we could even return
the result of calling [Link](...):
public class Subclass extends Superclass {
// We're overriding the foo method (here, we
// assume that foo was declared with an int return
// type in the superclass).
public int foo(int a, int b) {
int x = 3 * a;
int y = 17 * b;
return [Link](x, y);
}
}
Reusing Superclass Behaviors:
The “super” Keyword…
70
We can use [Link](...) in
whatever way makes sense in carrying out a
subclass’s version of the method that is being
overridden.
Another important use of the super keyword
has to do with reusing constructor code.
Rules for Deriving Classes: The “Don’ts”
71
We shouldn’t change the semantics—i.e.,
the intention, or meaning—of a feature.
For example:
If the print method of a superclass such as Student is
intended to display the values of all of an object’s
attributes in the command window, then the print
method of a subclass such as GraduateStudent
shouldn’t, for example, be overridden so that it directs
all of its output to a file instead.
If the name attribute of a superclass such as Person is
intended to store a person’s name in “last name, first
name” order, then the name attribute of a subclass such
as Student should be used in the same fashion.
Rules for Deriving Classes: The “Don’ts”…
72
We can’t physically eliminate features, nor
should we effectively eliminate them by
ignoring them.
To attempt to do so would break the spirit of the “is
a” hierarchy. By definition, inheritance requires that
all features of all ancestors of a class A must also
apply to class A itself in order for A to truly be a
proper subclass.
If a GraduateStudent could eliminate the
degreeSought attribute that it inherits from Student,
for example, is a GraduateStudent really a Student
after all? Strictly speaking, the answer is no.
Rules for Deriving Classes: The “Don’ts”…
73
public class Student {
// Details omitted.
public void printStudentInfo() {
// Pseudocode.
print all attribute values ...
}
}
public class BadStudent extends Student {
// Details omitted.
// We're overriding the printStudentInfo method of Student by
// "stubbing it out" - that is, by providing it with an EMPTY method
// body, so that it effectively does NOTHING.
// (Note that this WILL compile!)
public void printStudentInfo() { }
}
Rules for Deriving Classes: The “Don’ts”…
74
We shouldn’t attempt to change a
method’s signature when we override it.
Example:
if the print method inherited by the Student class from
Person has the signature print(), then the Student class
can’t change this method’s header to accept an
argument, say, print(int noOfCopies). To do so is to
create a different method entirely, due to another
language feature known as overloading.
Rules for Deriving Classes: The “Don’ts”…
75
Example:
public class Person {
// Details omitted.
public void print() { ... }
}
public class Student extends Person {
// Details omitted.
// We're naively trying to modify the print method signature
here.
public void print(int noOfCopies) { ... }
}
Private Features and Inheritance
76
inheritance is an “all or nothing” proposition. i.e.,
if class Y is declared to be a subclass of class X
public class Y extends X { ... }
then Y cannot pick and choose which features of
X it will inherit.
While all of the attributes declared by X will become an
inherent part of the “bon structure” of all objects of type Y,
some of the attributes of superclass X may not be inherited
by Y, so they are not directly referenceable by name
within subclass Y, depending on what accessibility the
attributes were assigned in the superclass.
Private Features and Inheritance…
77
Consider the following <accessibility modifier>
code: can be one of the
public class Person { following:
private
<accessibility
modifier> int age; public
// Other details omitted. protected (an
} accessibility modifier
that is only relevant
within a
superclass/subclass
relationship.
Private Features and Inheritance…
78
If age is declared to be private in
Example: Person, as most attributes
We declare a method typically are
(isOver65) that public class Person {
manipulates the age private int age;
attribute. // etc.
}
then we’ll encounter a
compilation error
Private Features and Inheritance…
79
What can we do to get
around this roadblock?
Option #1: We can
change the accessibility
of age to be public in
Person:
public class Person {
public int age;
// etc.
}
Private Features and Inheritance…
80
Client code
This would compile, but
is undesirable.
Private Features and Inheritance…
81
Option #2: We could modify
the accessibility of age to be
protected in Person:
public class Person {
protected int age;
// etc.
}
protected features are
inherited by/in scope within
subclasses; i.e., age would
now be recognized as a
symbol in the Student class,
such that
if (age > 65) return true;
would compile in Student.
Private Features and Inheritance…
82
However, protected
features are not
accessible by classes that
aren’t derived from the
superclass.
[Link] = 23; would
NOT compile if age
were declared to be
protected in Person
Private Features and Inheritance…
83
Option #3: The best
approach is to allow age to
remain a private attribute of
Person, but to use the
publicly accessible getAge/
setAge methods that we
inherit from the Person class
to manipulate the value of a
Student’s age:
Inheritance and Constructors
84
Constructors Are Note the redundancy of
logic between this
Not Inherited: constructor and the Person
Challenges constructor
we'll come back and fix
this in a moment.
Inheritance and Constructors…
85
// Constructor with three
arguments.
public Student(String n, String
s, String m) {
// More redundancy!
// Initialize our attributes.
[Link](n);
[Link](s);
[Link](m);
// Pseudocode.
do other complex things related to
instantiating a Person ...
... and still more complex things
related to instantiating a Student
specifically.
}
}
Inheritance and Constructors…
86
The first thing that we notice is that we’ve duplicated
code that was provided by the Person constructor in
both of the constructors for the Student class.
// Initialize our attributes.
[Link](n);
[Link](s);
// Pseudocode.
do other complex things related to instantiating a Person ...
code redundancy is to be avoided in an application
whenever possible; Java provides us with a
mechanism for reusing a superclass’s constructor
code from within a subclass’s constructor.
Inheritance and Constructors…
87
super(...) for Constructor Reuse
If we wish to explicitly reuse a particular
parent class’s constructor, we refer to it as
follows in the subclass constructor body:
super(arguments); // note that there is no "dot" involved
// when reusing CONSTRUCTOR code
Using super(arguments); to invoke a
superclass constructor is similar to using
this(arguments); to invoke one constructor
from within another in the same class.
Inheritance and Constructors…
88
We select whichever of a superclass’s
constructors we wish to reuse, if more than
one exists, by virtue of the arguments that we
pass in to super(...); because constructors, if
overloaded for a given class, all have unique
argument signatures, the compiler has no
difficulty in sorting out which superclass
constructor we’re invoking.
Inheritance and Constructors…
89
name and ssn are inherited // Constructor with three arguments.
from Person ... public Student(String n, String s,
String m) {
We're explicitly invoking the
// See comments above.
Person constructor that super(n, s);
accepts two String arguments [Link](m);
by passing in two String // Pseudocode.
arguments - namely, the do complex things related to
values of n and s. instantiating a Student specifically.
Then, go on to do only those }
}
things that need to be done
uniquely for a Student.
Inheritance and Constructors…
90
If we explicitly call a
superclass constructor from a
subclass constructor using the
super(...) syntax, the call
must be the first statement
in the subclass constructor
The following constructor
would fail to compile:
Inheritance and Constructors…
91
When we create a Student object, we are in
reality simultaneously creating an Object, a
Person, and a Student, all rolled into one.
So, whether we explicitly call a superclass constructor
from a subclass constructor using super(...) or not, the
fact is that Java will always attempt to execute
constructors for all of the ancestor classes for a given
class, from most general to most specific in the class
hierarchy, before launching into that given class’s
constructor code.
Inheritance and Constructors…
92
For example, if we are instantiating a Student
Student s = new Student("Fred", "123-45-6789");
then, behind the scenes, an Object constructor will
automatically be executed first, followed by a
Person constructor, followed by whichever Student
constructor we’ve explicitly invoked—in this
example, the one that takes two String arguments.
The question is, which superclass constructors
get called if there’s more than one defined
for a given superclass? Unless we explicitly
invoke a particular constructor as we did in our
Student constructors.
Inheritance and Constructors…
93
Example:
public Student(String n, String s) {
super(n, s);
// etc.
then the parameterless constructor for the superclass is called
automatically. That is, if we write
a constructor without an explicit call to super(args), as follows:
public Student(String n, String s) {
// NO EXPLICIT CALL TO super(...)
[Link](n);
[Link](s);
[Link]("UNDECLARED");
// etc.
}
Inheritance and Constructors…
94
it is as if we’ve written
public Student(String n, String s) {
super(); // implied
[Link](n);
[Link](s);
[Link]("UNDECLARED");
// etc.
}
instead. Herein arises a potential
problem,
Replacing the Default Parameterless Constructor
95
If we don’t bother to define any explicit
constructors for a particular class, then Java
will attempt to provide us with a default
parameterless constructor for that class.
When we invoke the default constructor for a
derived class such as Student, the compiler
will automatically try to invoke a
parameterless constructor for each of the
ancestor classes in the inheritance hierarchy
in top-down fashion.
Replacing the Default Parameterless Constructor…
96
Example: public class Student extends
Person {
public class Person { // Attributes ... details omitted.
// Attributes ... details // NO EXPLICIT CONSTRUCTORS
omitted. PROVIDED!!!
// NO EXPLICIT CONSTRUCTORS // We're going to be "lazy," and let
PROVIDED!!! Java provide us with
// We're going to be "lazy," and let // a default parameterless
Java provide us with constructor for the Student class.
// a default parameterless // Methods ... details omitted.
constructor for the Person class. }
// Methods ... details omitted.
}
Replacing the Default Parameterless Constructor…
97
it is as if we’ve designed our classes as public class Student extends Person {
follows:
// Attributes ... details omitted.
// [Link]
// The default parameterless Student
public class Person { constructor essentially would
// Attributes ... details omitted. // look like this if we were to code it
// The default parameterless Person explicitly:
constructor essentially would
// look like this if we were to code it explicitly:
public Student() {
public Person() { // Calling the default constructor for
// Calling the default constructor for the the Person class.
Object class. super();
super();
}
}
// Methods ... details omitted.
// Methods ... details omitted.
} }
Replacing the Default Parameterless Constructor…
98
If we derive a class B from class A, and write
no explicit constructors for B, then the
(default) parameterless constructor of B
will automatically look for a
parameterless constructor of A.
Thus, code such as the following example
won’t compile:
Replacing the Default Parameterless Constructor…
99
public class Person {
private String name;
public class Student extends
// We've written an explicit constructor with one Person {
argument for
// this (super)class; by having done so, we've LOST
// Attributes ... details omitted.
the // NO EXPLICIT CONSTRUCTORS
// Person class's default parameterless PROVIDED!!!
constructor.
public Person(String n) {
// We're going to be "lazy," and let Java
name = n; provide us with
} // a default parameterless constructor
// Note that we haven't bothered to REPLACE the for the Student class.
parameterless
// constructor with one of our own design. This is // Methods ... details omitted.
going to
// cause us problems, as we'll see in a moment.
}
// Methods ... details omitted.
}
Replacing the Default Parameterless Constructor…
10
This is because the Java compiler is 0
trying to create a default
parameterless constructor with no
arguments for the Student class. In
order to do so, the compiler knows
that it is going to need to be able to
invoke a parameterless constructor
for Person from within the Student
default constructor—however, no
such constructor for Person exists!
The best way to avoid such a
dilemma is to remember to always
explicitly program a
parameterless constructor for a
class X any time you program any
explicit constructor for class X, to
replace the “lost” default
constructor.
A Few Words About Multiple Inheritance
10
All of the inheritance 1
hierarchies that we’ve looked
at in this chapter are known
informally as single-
inheritance hierarchies,
because any particular class in
the hierarchy may only have a
single direct
superclass/immediate
ancestor.
Classes B, C, and I all have
the single direct superclass
A.
Classes D, E, and F have the
single direct superclass B.
Classes G and H have the
single direct superclass E.
A Few Words About Multiple Inheritance…
10
2
There are many complications inherent in
multiple inheritance—Java language designers
chose not to support multiple inheritance.
Instead, they’ve provided an alternative mechanism for
handling the requirement of creating an object with a
“split personality”: that is, one that can behave like
two or more different real-world entities.
This mechanism involves the notion of interfaces.
If you’re curious as to why multiple inheritance is so tricky,
then please read on the next few slides.
A Few Words About Multiple Inheritance…
10
3
with inheritance, a subclass automatically
inherits the attributes and methods of its
superclass.
What about when we have two or more direct
superclasses?
If these superclasses have no overlaps in terms of their
features, then we are fine.
But, what if the direct superclasses in question were,
as an example, to have conflicting features—perhaps
public methods with the same signature, but with
different code body implementations.
A Few Words About Multiple Inheritance…
10
4
public class Person {
private String name;
// Accessor method details omitted.
public String printDescription() {
[Link](getName());
// e.g., "John Doe"
}
}
A Few Words About Multiple Inheritance…
10
5
Later on, we decide to specialize Person by
creating two subclasses—Professor and
Student— which each add a few attributes
along with overriding the printDescription
method to take advantage of their newly
added attributes, as follows:
A Few Words About Multiple Inheritance…
10
6
public class Student extends Person {
// We add two attributes.
private String major;
private String studentId;
// Accessor method details omitted.
// Override this method as inherited from Person.
public String printDescription() {
return getName() + " [" + getMajor() + "; " +
getStudentId() + "]";
// e.g., "Mary Smith [Math; 10273]"
}
}
A Few Words About Multiple Inheritance…
10
7
public class Professor extends Person {
// We add two attributes.
private String title;
private String employeeId;
// Accessor method details omitted.
// Override this method as inherited from Person.
public String printDescription() {
return getName() + " [" + getTitle() + "; "
+ getEmployeeId() + "]";
// e.g., "Harry Henderson [Chairman; A723]"
}
}
A Few Words About Multiple Inheritance…
10
8
Note that both subclasses have overridden the printDescription
method differently, to take advantage of each class’s own unique
attributes.
At some future point in the evolution of this system, we determine
the need to represent a single object as both a Student and a
Professor simultaneously, and so we create the hybrid class
StudentProfessor as a subclass of both Student and Professor.
We don’t particularly want to add any attributes or methods—we
simply want to meld together the characteristics of both
superclasses—and so we’d ideally like to declare StudentProfessor as
follows:
// * * * Important Note: this is not permitted in Java!!! * * *
public class StudentProfessor extends Professor and Student {
// It's OK to leave a class body empty; the class itself is not
// REALLY "empty," because it inherits the features of all of its
// ancestors.
}
A Few Words About Multiple Inheritance…
10
9
However, we encounter a roadblock to doing so:
StudentProfessor cannot inherit both the Professor and Student
versions of the printDescription method, because we’d then wind up
with two (overloaded) methods with identical signatures in
ProfessorStudent, which is not permitted by the Java compiler.
Chances are that we’ll want to inherit neither, because neither one
takes full advantage of the other superclass’s attributes. That is, the
Professor version of printDescription knows nothing about the
getMajor and getStudentId methods inherited from Student, nor does
the Student version of printDescription know about the getTitle or
getEmployeeId methods inherited from Professor.
If we did wish to use one of the superclass’s versions of the method
versus the other, we’d have to invent some way of informing the
compiler of which one we wanted to inherit.
This is just a simple example, but it nonetheless illustrates
why multiple inheritance can be so problematic.
Comments/Suggestions
11
0