Object-Oriented Programming

Encapsulation

Michael L. Collard, Ph.D.

Department of Computer Science, The University of Akron

Credits

Adapted from: Encapsulation is not information hiding

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 for Class A

Access Type Visible
public any code
protected class A methods, friends of class A, or a class derived from class A
private class A methods, friends of class A

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 a local variable could be used instead of 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 the minimum functionality and configurability, and add as needed

Position v0

Position v0 Analysis

  • Data, latitude and longitude, in the Position class
  • Operations, distance() and heading(), are free functions in a separate file
  • Client program has to include two files
  • Easy to get the order of arguments backward 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 client tie data and operations together
  • Provide it in one class (or the 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

  • Make all data members private
  • If access is needed externally to the class, use get and set methods for access
  • Isolates client from changes to data members (if the same external functionality is needed)

Position v2

What Not To Do

  • Non-const reference takes const off of the method
  • Pretty much the same as making the field public
  • Very few applications where this makes 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 reference

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 data
  • 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()

  • Changing to radians internally would make everything much simpler
  • Do not want to change the current interface (i.e., in degrees), as clients expect it
  • However, we 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 the client code has to change
  • Use of auto in the client code, and perhaps a typedef can help, but not entirely 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 to a container that does not allow indexing, the 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, the 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 allow iteration through segments and not positions