Title: Encapsulation
1 Encapsulation and Class Design The contents
of this lecture prepared by the instructors at
the University of Manitoba in Canada and modified
by Dr. Ahmad Reza Hadaegh
2Objects So Far - So far objects just look like
the method we showed for combining
heterogeneous data together - It looked like an
array, but we access components by name rather
than position - But there's much more to them
than that - The use of true object-oriented
programming is best seen from examining the
nature of physical objects - Suppose you had a
factory and wanted to make a remote-controlled
car
3Extending our Concept of Objects - Think about
what you'd specify in the design of the car -
Lots of data, like length, width, colour - also
subcomponent objects engine, etc... - So an
obvious application to the objects we've used
so far - But you'd also need other things
what the car's supposed to do if we turn the
control left or when we step on the break
4Operations and Objects - These are operations,
not data, but the car's behaviors are just as
much a part of the car when we think about
building one - Objects let us include operations
as members as well! - Object-oriented
programming involves defining the data
components of an object, and also the
operations we perform on the object, and
bundling them together into a single package
5Classes and Instances - This analogy also makes
the relationship between classes and instances
clearer - We define a Car class to encompass all
the choices we've made in our car design - It
serves as a general model for the factory - Then
we crank out many instances of the Car class
(and here, hopefully sell them for big
bucks) - This analogy will also explain many
other aspects of Object-Oriented Programming
that we will see later
6Operations and Objects - Recall our problem with
our length class - there was nothing
restricting us from referring to the internal
components of a length object from anywhere -
Thus big problem occurs if we ever changed
length! - We can simply define the legal
operations for an object of type length, and
make them part of length itself! - Then
they're in one spot, and we only have to ever
make changes in one place - Let's see what this
looks like...
7Adding Functions - we'll add routines to read
and print a length - For example class Length
int minutes int seconds public void
input() void print()
8Adding Functions - This definition specifies a
new class Length - Similar to our earlier Length
class, except the functions that operate on
Length are included in our definition - They
look just like normal function headers - the
odd part is the bodies are separate (we'll
define them in a few minutes) - The class
contains Data members and function members -
Function members are also called methods
9Instantiation - Remember that a class definition
only creates a new type we need to declare
objects/variables of that class Length
the_length the_length is an instance of the
class Length - also called an object of class
(or type) Length Our declaration of
the_length reserves space for the data
members and We still need to define the
methods
10Implementation - We do this the same way as any
other function, with a little extra syntax
void Lengthinput( ) void
Lengthprint( ) cin gtgt minutes
gtgt seconds cout ltlt minutes ltlt ltlt
seconds - These go outside the
definition of the length class - it makes sense
to keep them close though! - Length
specifies that the function were defining
isn't global, but belongs to the Length class.
Could have a global input/print too!
11- Notice that within Length, we refer to the
variables without dot notation - i.e., we say
minutes instead of the_ length.minutes - This
should make sense - remember why we use the
dot notation - normally we'd use the the_length
prefix to specify the object whose minutes
member we want - but when this is executing
we're INSIDE that object - there's only one
minutes member we could possibly be referring
to!
12- Weve already seen class methods, although we
havent been calling them that - Calling a
method the_length.print(cout) - In other
words, we call a method in the same way that we
specify any other member, using .
13Scope - Our print() method, has one line of code
in it cout ltlt minutes ltlt ltlt seconds -
When we call the_length.print( ) minutes
and seconds in the method refer to the_lengths
minutes and seconds members All this boils down
to - The scope of class members extends to
the class methods
14Inside the Method - If we declare another object
of type Length, it will have different minutes
and seconds members - for example
Length the_length1, the_length2 the_length1.i
nput( ) the_length2.input( ) the_length1.print
( ) the_length2.print( )
15Back to the idea of protection - Remember we
brought up the idea of embedding functions in
objects as a means of ensuring that code we
write doesn't depend on the physical
implementation of our class - Instead of having
several functions from all over referring to
the internal data members of length, and having
to change all those when we change the
internals of length - We declare what we need
INSIDE length and allow other objects to use
those functions
16Back to the idea of protection - That way NOBODY
but the length object itself knows OR CARES
about what's stored internally - In this case,
they just know that they can call input or
print and get what they need! - Everything else
is INDEPENDENT of length - BUT - there's still
nothing FORCING us to use this YET!
17Information Hiding - This general concept is
called Information Hiding and is one of the
major benefits of using Object-Oriented
methodologies - C provides very nice
mechanisms for enforcing the ideas we've just
covered. In fact we've even seen a sign of
them. - The word "public" has been put in every
class we've made so far - Classes allow us to
select what parts to hide
18Information Hiding - Members of the class
following the public specification can be
accessed anywhere - So for example, we want our
input and print functions to be public in our
Length class - we WANT other's to be able to use
them! - Any other members are considered
private We can also explicitly declare members
as private using the private
specification - Private members can be accessed
in member functions (methods) - So anything we
put before the "public" can only be seen/
changed inside the class!
19Private Specification class Length
public void input( ) void print(
) private int minutes int seconds -
So, in our example, we can make minutes and
second as private members so that only the
two public members (input and print methods)
can access them.
20 - In general, Any function or data member can be
public or private - By specifying members as
either public or private, we can decide what
parts of our class are visible to the rest of our
program, and which are hidden - Thus, as
long as the public stuff looks the same, we can
change our private members at will! - For
example, if we wanted to change the way we store
minutes and seconds to a float (whole number
is minutes, fractional part is seconds), we
can do that - And ANY OTHER PART of our program
will be completely unaffected, because they
couldn't possibly be using those members
21Changing the Implementation class Length
public void input( ) void print(
) private float time - Now we could
change our input() and print() methods
appropriately - Notice functions using
(calling) input and print don't have to change!
22The Interface - Our Length class can only be
accessed through the input() and print()
methods - These methods make up the interface to
our class - The part the user of the object gets
to see and work with - Anything public is
part of the interface
23Designing Classes - Programming classes is a
little different from what weve been doing so
far - The programs that youve designed already
(like the assignments) solved problems by
dividing them into smaller tasks - Each task was
implemented as a function Rather than dividing
things into tasks, we start by looking at the
data we are working with. - In object-oriented
programming and design, we design our classes
by dividing up the data by logical relationships
24Designing Classes - Then we need to decide what
we need to do with our data - This helps us
create our interface - For example, it was
decided (beforehand) that our Length class was
going to be used in our list of music albums -
We would be reading in the list of albums (from a
file or the keyboard), and writing them out -
So the only two methods that we need are input()
and print()
25Encapsulation - We can make that easier by
separating the implementation of our class from
where its declared this is called
encapsulation - In practice, usually do this by
placing our implementation in a separate source
code file - We would create a file called
length.cpp containing our two function
declarations
26- The Interface
- - In order to use our class in a program, we
- need to have the class definition specified
- somewhere
- - We would put it in a header file length.h
- - Now weve (mostly) split things up
- according to our design
- length.cpp contains our implementation
- length.h contains our interface (the
specification file) - our main program uses the Length class
-
- ltSee Example 1, 2gt
27Constructors - A constructor is a function that
gets called each time an instance of a class
is created - Defining a constructor ensures that
when we create an instance, it has some sort
of (meaningful) initial value - A constructor is
a method (member function) which has the same
name as the class itself class Length
public Length() ... - Notice the
syntax no return type is specified!
28Default Constructors - This particular
constructor takes no parameters, and gets
called when we instantiate our class like
this Length the_length - We call this the
default constructor - it doesn't do much! - The
implementation might look like this LengthLen
gth() minutes 0 // a gain, inside the
object, so no '. '! seconds 0
29Constructors, contd - We can also have a
constructor that takes one or more
parameters class Length public Length (int,
int) // Our default constructor can be
specified // as well - c knows which one to
use by // the number types of parameters //
supplied when calling it! Length()
30Constructors, contd - This constructor gets
called when we instantiate our class with
parameters Length the_ length( 1, 43) - Our
implementation might be Length Length( int
mins, int secs) // Initialize our class to
the given number of // minutes and
seconds minutes mins seconds secs
31Constructors, contd - Theres an odd
interaction between default constructors and
ones which take parameters - A default
constructor exists even if you dont
explicitly write one (it just doesnt do
anything) - But if you specify a constructor
that takes parameters, and no default
constructor, then the class has no default
constructor
32- Lets say Length has no constructors at all
Length the_ length // Calls the default
constructor - This works - we havent written
a default constructor, but one still exists
(the one that does nothing) - Lets add a
constructor that takes parameters, like
Length Length( int, int) Length len1(1, 43)
// OK, calls Length( int, int) Length len2
// Error! No default constructor! - This is
important because we cannot use a constructor
with parameters when we make an array of
class instances - Arrays require a default
constructor (or no constructors at all)
33Destructors - The opposite of constructors -
Destructors are functions that get called when
our variable is destroyed (e.g. goes out of
scope) - They look like this class Length
public Length() // Destructor
... - We dont have much of a use for these
yet