Object-Oriented Programming

Encapsulation & Information Hiding

Michael L. Collard, Ph.D.

Department of Computer Science, The University of Akron

Definitions

  • Encapsulation

    the bundling of data with the methods that operate on that data

  • Information Hiding

    hide the internal representation, or state, of an object from the outside

  • Note: Some definitions of encapsulation include the definition of information hiding

Language Features

  • C language support:
    • struct with fields only, and no access specifiers
    • free functions
  • C++ language support:
    • class Integrate data with methods
    • Access specifiers: public, private, protected

Access & Visibility

Access Type Visible
public any code
protected internal methods or friends of a class or derived class
private internal methods or friends of a class

First Rule: Limit the Interface

  • Limit methods available
  • Limit the access and visibility
    • I.e., private whenever possible
  • Remove any unneeded parameters
    • E.g., code where what is a local variable could be a parameter
  • Use const whenever possible for reference and pointer parameters and methods

Minimum Essential Interface

  • Unless required, more is not better
  • Developers tend to overdesign and provide more than is needed (sometimes missing what is needed)
    • E.g., A study at Microsoft showed that 30% of methods identified in the design of software were never implemented
  • Start with minimum functionality and configurability, and add as needed

Position v0 struct & functions

Position v0 Usage

Adapted from

Position v0 Analysis

  • Data, latitude and longitude, in class Position
  • Operations, distance() and heading(), are free functions in a separate file
  • Client program has to include two files
  • Easy to get order of arguments backwards heading() and calculate the opposite of what is needed

Other Position v0 Issues

  • Fields of struct Position are public and directly accessible. It is possible to store invalid latitude and longitude values, producing garbage distance and headings (GIGO)
  • Changes to the field/data member names, types, or even storage in Position require changes in the implementation of distance() and heading() (∆ Position.hpp ⟶ ∆ PathCalculations.cpp)

Encapsulation Rule

Place data and the operations that perform on that data in the same class

  • Don’t make the clients tie data and operations together
  • Provide it in one class (or fewest number of classes needed)
  • Improves the class cohesion

Position v1

Position v1 Analysis

  • Only need to include a single include file, Position.hpp
  • Clear direction of operations heading()

Information Hiding Rules

  1. Don’t expose data items
  2. Don’t expose the difference between stored data and derived data
  3. Don’t expose implementation details of a class
  4. Don’t expose a class’s internal structure

Information Hiding Rule 1

Don’t expose data items

  • All fields and data members private
  • Use @get and @set methods for access if needed externally to class
  • Isolates client from changes to data members (if same external functionality is needed)

Position v2

What Not To Do

  • Non-const reference takes const off of method
  • Pretty much the same as making the field public
  • Very few applications where this make sense
  • Specially a problem in Java, as Objects are not passed by value, but by Object Reference, and there isn’t a const
  • Instead: Always return data by value or const &

As Far As A Mutator

Information Hiding Rule 2

Don’t expose the difference between stored data and derived data

  • Derived data is data calculated from stored date
  • Don’t reveal whether an attribute is stored or derived
  • Use @get method names for @property methods:
  • @get method names: speed(), getSpeed()
  • @property method names: calculateSspeed(), determineSspeed()

Position v2 Position::distance()

Observation

  • Changing to radians internally would make everything much simpler
  • Do not want to change current interface (i.e., in degrees), as clients expect it
  • However, could add radians to the interface, while preserving what we have

Position v2 -> v3

Position v2 & v3 Interface

Position v2 & v3 Client

Position::distance() v2 -> v3

Position:getLatitude() v2 -> v3

New Requirement

  • Need to handle a multi-position route

Route v0

Information Hiding Rules

  1. Don’t expose data items
  2. Don’t expose the difference between stored data and derived data
  3. Don’t expose implementation details of a class
  4. Don’t expose a class’s internal structure

Route v0 Issues

  • Can directly access elements of an internal container
  • Can we change the container?
  • Can we change the container values?

Route v0 & v1 Interface

Information Hiding Rules

  1. Don’t expose data items
  2. Don’t expose the difference between stored data and derived data
  3. Don’t expose implementation details of a class
  4. Don’t expose a class’s internal structure

Route v1 Issues

  • Exposes direct design detail that we are using a std::vector
  • If we change to a different container, the type returned by the getPositions() has to change, and client code has to change
  • Use of auto in the client code, and perhaps a typedef can help, but not completely prevent this
  • Which container we use is an internal structure and implementation detail that should be hidden in the class
  • Do we need this type of access?

Route v1 & v2 Interface

Route v2 Issues

  • The setPosition() exposes direct design detail that we are using an indexable container
  • If we change a container that does not allow indexing, client code would have to change
  • The characteristics of which container we use is an internal structure and implementation detail that should be hidden in the class
  • Do we need this type of access?

Route v2 & v3 Interface

Route v3 Issues

  • The getPosition() is expected to be a O(1) or constant-time algorithm
  • However, with a non-indexable container, e.g., std::list, this is not true
  • If we change a container that does not allow indexing, client code would have to change
  • The characteristics of which container we use is an internal structure and implementation detail that should be hidden in the class
  • Do we need this type of access?

Route v3 & v4 Interface

Route v4 Improvements

  • Use standard C++ iterators

Route v4 & v5 Interface

Route v5 Additional Improvements

  • A separate iterator object would allow multiple, simultaneous access
  • A begin() and end() would allow use in range-for statement
  • The segment is problematic. Perhaps just allow iteration through segments and not positions