JMU JMU - Department of Computer Science
Help Tools
Lab: Gaining Experience with Overloading


Instructions: Answer the following questions one at a time. After answering each question, check your answer (by clicking on the check-mark icon if it is available) before proceeding to the next question.

Getting Ready: Before going any further, you should:

  1. Depending on your development environment, create either a directory or a project for this lab.
  2. Setup your development environment.
  3. Download the following files:
    to an appropriate directory/folder. (In most browsers/OSs, the easiest way to do this is by right-clicking/control-clicking on each of the links above.)

1. Overloading Methods: This part of the lab will give you some experience writing overloaded methods.
  1. The current version of the Test class has multiple methods that test for equality, each with a slightly different name and different parameters. Modify the code so that it now has three overloaded forEqual() methods one with double parameters one with int parameters, and one with String parameters. What does the class look like now?


    solution/Test.java
            /**
     * A simple unit testing harness.
     *
     * @author  Prof. David Bernstein, James Madison University
     * @version 3.0 (Uses overlaoded methods)
     */
    public class Test {
    
        /**
         * Display an alert if the actual double value and the expected double
         * value differ by more than the given tolerance.
         *
         * @param description  A description of the test
         * @param expected     The expected value
         * @param actual       The actual value
         * @param tolerance    The tolerance
         */
        public static void forEqual(String description, 
                                    double expected, double actual,
                                    double tolerance) {
            double difference;
            
            difference = Math.abs(expected - actual);
            if (difference > tolerance) {
                System.out.printf("%s Expected: %5.2f, Actual: %5.2f\n", 
                                  description, expected, actual);
            }
        }
        
        /**
         * Display an alert if the actual int value is not equal to the
         * expected value.
         *
         * @param description  A description of the test
         * @param expected     The expected value
         * @param actual       The actual value
         */
        public static void forEqual(String description, 
                                    int expected, int actual) {
    
            if (expected != actual) {
                System.out.printf("%s Expected: %d, Actual: %d\n", 
                                  description, expected, actual);
            }
        }
        
        /**
         * Display an alert if the contents of the actual String object
         * is not not equal to the contents of the expected value String object.
         *
         * @param description  A description of the test
         * @param expected     The expected value
         * @param actual       The actual value
         */
        public static void forEqual(String description, 
                                    String expected, String actual) {
    
            if (!expected.equals(actual)) {
                System.out.printf("%s Expected: %s, Actual: %s\n", 
                                  description, expected, actual);
            }
        }
    
        /**
         * Display an alert if the actual boolean is not false.
         *
         * @param description  A description of the test
         * @param actual       The actual value
         */
        public static void forFalse(String description, 
                                       boolean actual) {
            if (actual) {
                System.out.printf("%s Expected: false, Actual: true\n", 
                                  description);
            }
        }
        
        /**
         * Display an alert if the actual boolean is not true.
         *
         * @param description  A description of the test
         * @param actual       The actual value
         */
        public static void forTrue(String description, 
                                   boolean actual) {
            if (!actual) {
                System.out.printf("%s Expected: true, Actual: false\n", 
                                  description);
            }
        }
    }
            
    Expand
  2. Copy the JMUPhoneNumberDriver class you wrote for the lab on information hiding to your working directory.
  3. Modify this class so that it uses the new version of the Test class. (Hint: Use Find/Replace.)
  4. Copy the JMUPhoneNumber class you wrote for the lab on information hiding to your working directory.
  5. Overload the setExchange() method with a new version that is passed a single char. If the actual parameter is a '6' this method should set the exchange to DORM, otherwise it should set the exchange to OFFICE.


    solution/JMUPhoneNumber.java (Fragment: setExchange)
                /**
         * Set the exchange
         *
         * @param x   Either '6' or '8'
         */
        public void setExchange(char x)
        {
           if (x == '6') setExchange(DORM);
           else          setExchange(OFFICE);       
        }
            
    Expand
  6. Why can't this version of the setExchange() method have an int parameter?


    Because there is already a method with that name that has an int parameter.
    Expand
  7. Modify your driver so that it can be used to test the setExchange() methods.
  8. Execute your driver and test these methods.
  9. Overload the toString() method with a new version that is passed an int format code. (This method must not change the format associated with the JMUPhoneNumber object even temporarily. It must use the parameter that it is passed to create the String it returns.)


    This method is an exact copy of the original version. However, now because format is a parameter, the parameter will be used rather than the attribute.
    Expand
  10. Why should one version of the toString() method call the other version?


    To avoid code duplication.
    Expand
  11. Modify the toString() methods so that one calls the other.


    solution/JMUPhoneNumber.java (Fragment: toString)
            
        /**
         * Returns a formatted String representation of this JMUPhoneNumber
         * (see the discussion of the setFormat method)
         */
        public String toString()
        {
           return toString(this.format);       
        }
        
    
        /**
         * Returns a formatted String representation of this JMUPhoneNumber
         * (see the discussion of the setFormat method)
         *
         * @param tempFormat   The format code to use
         */
        public String toString(int tempFormat)
        {
           String      fourDigitExtension, result;
           
           fourDigitExtension = String.format("%04d",extension);       
           
           result = "";
    
           if      (tempFormat == US_OLD)
           {
              result = "("+areaCode+") "+exchange+"-"+fourDigitExtension;
           }
           else if (tempFormat == US_NEW)
           {
              result = areaCode+"-"+exchange+"-"+fourDigitExtension;          
           }
           else if (tempFormat == EUROPE)
           {
              result = areaCode+"."+exchange+"."+fourDigitExtension;          
           }
           else if (tempFormat == JMU)
           {
              if      (exchange == OFFICE) result = "x8-";
              else if (exchange == DORM)   result = "x2-";
    
              result += fourDigitExtension;          
           }
    
           return result;       
        }
            
    Expand
  12. Modify your driver so that it can be used to test the toString() methods.
  13. Execute your driver and test these methods.
  14. Add an implementation of the following equals() method to the JMUPhoneNumber class.
        /**
         * Determine if this JMUPhoneNumber has the given
         * areaCode, exchange and extension
         *
         * @param areaCode   The area code
         * @param exchange   The exchange
         * @param extension  The extension
         */
        public boolean equals(int areaCode, int exchange, int extension)
        {
    
        }
    


    solution/JMUPhoneNumber.java (Fragment: equals3)
                /**
         * Determine if this JMUPhoneNumber has the given
         * areaCode, exchange and extension
         *
         * @param areaCode   The area code
         * @param exchange   The exchange
         * @param extension  The extension
         */
        public boolean equals(int areaCode, int exchange, int extension)
        {
           return (this.areaCode  == areaCode)
               && (this.exchange  == exchange)
               && (this.extension == extension);
        }
            
    Expand
  15. Modify your driver so that it can be used to test the equals() method.
  16. Execute your driver and test this method.
  17. Modify the 1-parameter version of the equals() method so that it calls the 3-parameter version of the equals() method. (Changing a method without changing its external behavior is caused refactoring.)


    solution/JMUPhoneNumber.java (Fragment: equals1)
                /**
         * Determine if this JMUPhoneNumber has the same
         * areaCode, exchange and extension as the given JMUPhoneNumber
         *
         * @param other      The other JMUPhoneNumber
         */
        public boolean equals(JMUPhoneNumber other)
        {
           return equals(other.areaCode, other.exchange, other.extension);
        }
            
    Expand
  18. Execute your driver and test this method. (Running existing tests to ensure that changes have not introduced any defects is called regression testing.)
  19. Why should one version of the equals() method call the other version?


    To avoid code duplication.
    Expand
  20. One could implement these methods differently and have the the 3-parameter version of the equals() method call the 1-parameter version. Why would this be a bad idea? In other words, why should the 1-parameter version of the equals() method call the 3-parameter version? Or, put still another way, what would the 3-parameter version have to do in order to call the 1-paremeter version?


    The 3-parameter version would have to construct a JMUPhoneNumber object with the given area code, exchange, and extension. That object would then not be used for anything else and would have to be garbage collected. In general, this kind of thing should be avoided if possible.
    Expand
  21. Why is the 1-parameter version of the equals() method able to access the areaCode, exchange, and extension attributes of other when they are private?


    The definition of private is subtle in Java. Attributes and methods that are declated private are actually accessible to all objects in the class, not just the owning object. This can be dangerous!
    Expand
2. Overloading Constructors: This part of the lab will give you some experience writing overloaded constructors.
  1. Overload the constructor with a new version that is passed the exchange, extension, and format.


    solution/JMUPhoneNumber.java (Fragment: ev4Constructor)
                /**
         * Explicit Value Constructor
         *
         * @param areaCode   The area code
         * @param exchange   The exchange
         * @param extension  The extension
         * @param format     The format
         */
        public JMUPhoneNumber(int areaCode, int exchange, int extension, 
                              int format)
        {
           this.areaCode  = areaCode;
           this.exchange  = exchange;       
           this.extension = extension;
           this.format    = format;       
        }
            
    Expand
  2. Modify the default constructor so that it calls the explicit value constructor you just wrote.


    solution/JMUPhoneNumber.java (Fragment: defaultConstructor)
                /**
         * Default Constructor
         *
         * Constructs a JMUPhoneNumber with the areaCode set to 540,
         * the exchange set to 568, the extension set to 6211, and the
         * format set to JMU
         */
        public JMUPhoneNumber()
        {
           this(540, 568, 6211, JMU);       
        }
            
    Expand
  3. Modify your driver so that it can be used to test these constructors.
  4. Execute your driver and test these constructors.
  5. Write another constructor that is passed just an extension. This version should assume that the area code is 540, the exchange is OFFICE and that the format is US_OLD. (This constructor should call another constructor in the same class.)


    solution/JMUPhoneNumber.java (Fragment: ev1Constructor)
                /**
         * Explicit Value Constructor
         *
         * @param extension  The extension
         */
        public JMUPhoneNumber(int extension)
        {
           this(540, OFFICE, extension, US_OLD);
        }
            
    Expand
  6. Modify your driver so that it can be used to test this constructor.
  7. Execute your driver and test this constructor.
  8. Add an implementation of the following copy constructor to the JMUPhoneNumber class. Note: This constructor must call one of the other constructors.
        /**
         * Copy Constructor
         *
         * @param original  The JMUPhoneNumber to copy
         */
        public JMUPhoneNumber(JMUPhoneNumber original)
        {
    
        }
    


    solution/JMUPhoneNumber.java (Fragment: copyConstructor)
                /**
         * Copy Constructor
         *
         * @param original  The JMUPhoneNumber to copy
         */
        public JMUPhoneNumber(JMUPhoneNumber original)
        {
           this(540, original.areaCode, original.extension, original.exchange);
        }
            
    Expand
  9. Modify your driver so that it can be used to test this constructor.
  10. Execute your driver and test this constructor.
  11. Why should the different constructors call each other?


    Otherwise they would have to contain duplicate code which is likely to lead to inconsistencies in the future.
    Expand

Copyright 2019