JMU
An Introduction to Information Hiding
with Examples in Java


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Review
The Process Thus Far
  1. Read the textual description
  2. Create an initial encapsulation
  3. Add a constructor
  4. Add a toString() method
  5. Add an equals() and/or compareTo() method
A Motivating Example
A General Principle
Information Hiding Guidelines
"Immediate" Benefits of Information Hiding
"Immediate" Benefits of Information Hiding (cont.)
An Example

An Improved PictureFrame Class

javaexamples/oopbasics/pictureframe/privateattributes/PictureFrame.java
/**
 * An encapsulation of a picture frame.
 *
 * This version makes use of information hiding. In particular,
 * it makes the attributes private, adds accessors (but not mutators),
 * and other useful methods.
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 2.0
 */
public class PictureFrame
{
    private boolean    stand;    
    private double     height, matte, width;
    
    /**
     * Construct a PictureFrame object.
     *
     * Note: Negative values are converted to positive values 
     * and the width and height are put in canonical form 
     * (i.e., a portrait orientation).
     *
     * @param width   The width (in inches)
     * @param height  The height (in inches)
     * @param matte   The size of the matte (in inches) on all 4 sides
     * @param stand   true if there is a built-in stand
     */
    public PictureFrame(double width, double height, double matte, 
                        boolean stand)
    {
        double     h, w;
        
        h = Math.abs(height);
        w = Math.abs(width);

        this.width  = Math.min(w, h);
        this.height = Math.max(w, h);
        this.matte  = Math.abs(matte);
        this.stand  = stand;
    }

    /**
     * Return true if the owning PictureFrame and the given PictureFrame
     * have the same attributes.
     *
     * @return  true if the attributes are the same; false otherwise
     */
    public boolean equals(PictureFrame other)
    {
        return (this.width == other.width) && (this.height == other.height)
            && (this.matte == other.matte) && (this.stand == other.stand);
    }

    /**
     * Return the cost of this PictureFrame (which is a function
     * of the perimeter and the area) in dollars.
     *
     * @return   The cost
     */
    public double getCost()
    {
        double     frame, glass;
        
        frame = (2.0*width + 2.0*height) * 0.15;
        glass = (width * height) * 0.05;

        return frame+glass;
    }

    /**
     * Get the height of this PictureFrame.
     *
     * @return   The height
     */
    public double getHeight()
    {
        return height;
    }

    /**
     * Get the size of the matte.
     *
     * @return   The size of the matte
     */
    public double getMatte()
    {
        return matte;
    }

    /**
     * Get the width of this PictureFrame.
     *
     * @return   The width
     */
    public double getWidth()
    {
        return width;
    }

    /**
     * Return the visible area (in square inches) of the content
     * contained in this PictureFrame.
     *
     * @return   The visible area
     */
    public double getVisibleArea()
    {
        return (width - 2.0*matte) * (height - 2.0*matte);
    }

    /**
     * Return a human-readable String representation of this PictureFrame.
     *
     * @return  The String representation
     */
    public String toString()
    {
        String      result;
        
        result = String.format("%5.2f in. x %5.2f in.", width, height);
        if (matte > 0.0)
            result += String.format(" with a %5.2f in. matte", matte);
        if (stand)
            result += " (w/ stand)";
        
        return result;
    }
}
        
Using Private Methods
An Example (cont.)

An Even Better PictureFrame Class

javaexamples/oopbasics/pictureframe/privatemethods/PictureFrame.java
/**
 * An encapsulation of a picture frame.
 *
 * This version has overloaded methods.
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 6.0
 */
public class PictureFrame
{
    private static final double DOLLARS_PER_IN_OF_FRAME    = 0.15;
    private static final double DOLLARS_PER_SQ_IN_OF_GLASS = 0.05;    

    private boolean    stand;    
    private double     height, matte, width;

    /**
     * Construct a PictureFrame object.
     *
     * Note: Negative values are converted to positive values 
     * and the width and height are put in canonical form 
     * (i.e., a portrait orientation).
     *
     * @param width   The width (in inches)
     * @param height  The height (in inches)
     * @param matte   The size of the matte (in inches) on all 4 sides
     * @param stand   true if there is a built-in stand
     */
    public PictureFrame(double width, double height, double matte, 
                        boolean stand)
    {
        double     h, w;
        
        h = Math.abs(height);
        w = Math.abs(width);

        this.width  = Math.min(w, h);
        this.height = Math.max(w, h);
        this.matte  = Math.abs(matte);
        this.stand  = stand;
    }
    
    /**
     * Construct a PictureFrame object with no matte and no stand.
     *
     * @param width   The width (in inches)
     * @param height  The height (in inches)
     */
    public PictureFrame(double width, double height)
    {
        this(width, height, 0.0, false);
    }
    
    /**
     * Default Constructor.
     *
     * Construct a 3x5 PictureFrame with no matte and no stand.
     */
    public PictureFrame()
    {
        this(3.0, 5.0, 0.0, false);
    }
    
    /**
     * Copy Constructor.
     *
     * @param other   The PictureFrame to copy
     */
    public PictureFrame(PictureFrame other)
    {
        this(other.width, other.height, other.matte, other.stand);
    }

    /**
     * Calculate the area of this PictureFrame.
     *
     * @return  The area (in square inches)
     */
    private double area()
    {
        return width * height;
    }

    /**
     * Calculate the area of the matte.
     *
     * @return  The area (in square inches)
     */
    private double matteArea()
    {
               // Top and Bottom   + Sides (not including the top and bottom)
        return 2.0*(matte * width) + 2.0*(matte * (height - 2.0*matte));
    }

    /**
     * Calculate the perimeter of this PictureFrame.
     *
     * @return  The area (in inches)
     */
    private double perimeter()
    {
        return 2.0*width + 2.0*height;
    }

    /**
     * Return true if the owning PictureFrame and the given PictureFrame
     * have the same attributes.
     *
     * @return  true if the attributes are the same; false otherwise
     */
    public boolean equals(PictureFrame other)
    {
        return (this.width == other.width) && (this.height == other.height)
            && (this.matte == other.matte) && (this.stand == other.stand);
    }

    /**
     * Return the cost of this PictureFrame (which is a function
     * of the perimeter and the area) in dollars.
     *
     * @return   The cost
     */
    public double getCost()
    {
        double     frame, glass;
        
        frame = perimeter() * DOLLARS_PER_IN_OF_FRAME;
        glass = area() * DOLLARS_PER_SQ_IN_OF_GLASS;

        return frame+glass;
    }

    /**
     * Get the height of this PictureFrame.
     *
     * @return   The height
     */
    public double getHeight()
    {
        return height;
    }

    /**
     * Get the size of the matte.
     *
     * @return   The size of the matte
     */
    public double getMatte()
    {
        return matte;
    }

    /**
     * Get the width of this PictureFrame.
     *
     * @return   The width
     */
    public double getWidth()
    {
        return width;
    }
    /**
     * Return the visible area (in square inches) of the content
     * contained in this PictureFrame.
     *
     * @param    max   true for the maximum possible (i.e., unmatted) area 
     * @return   The visible area
     */
    public double getVisibleArea(boolean max)
    {
        double   result;
        
        result = area();
        if (!max) result -= matteArea();

        return result;
    }

    /**
     * Return the visible area (in square inches) of the content
     * contained in this PictureFrame.
     *
     * @return   The visible area
     */
    public double getVisibleArea()
    {
        return getVisibleArea(false);
    }

    /**
     * Return a human-readable String representation of this PictureFrame.
     *
     * @param   terse  true for a terse representation
     * @return         The String representation
     */
    public String toString(boolean terse)
    {
        String      result;

        if (terse)
        {
            result = ""+width+"x"+height;
        }
        else
        {
            result = ""+width+"in. x "+height+"in.";
            if (matte > 0.0) result += " with a "+matte+"in. matte";
            if (stand)       result += " (w/ stand)";
        }
        
        return result;
    }

    /**
     * Return a human-readable String representation of this PictureFrame.
     *
     * @return         The String representation
     */
    public String toString()
    {
        return toString(false);
    }
}
        
Encapsulation is NOT Information Hiding
Another Important Term
The Process Thus Far
  1. Read the textual description
  2. Create an initial encapsulation with private attributes
  3. Add a constructor
  4. Add a toString() method
  5. Add an equals() and/or compareTo() method
  6. Add necessary accessors
  7. Add necessary mutators
  8. Add useful private methods (i.e., helper methods)