CSC152 2004F, Class 18: Exceptions (When Things Go Wrong) Admin: * Appropriate prospective attire. Bright pink, black, and white with "The Cure" on the back? * Tomorrow: Project discussion. Think about what you'd like to do. * Proposed * Pente * Four-year planner * Past * Online auction system * Email reader * Othello (with AI) * Homework: Compare/contrast inheritance and interfaces * Questions on the exam? * Bring some on Tuesday. Overview: * Inheritance concluded * Review * Writing constructors * Protection * Some examples * Things that can go wrong with programs * Dealing with errors * The Java solution: Exceptions * Catching exceptions * Throwing your own exceptions /Inheritance, Reviewed/ * We can build a new class based on another class by writing public class NewClass extends OldClass * NewClass immediately gets all of the methods and fields of OldClass. * NewClass may override the behavior of any of the inherited methods. * NewClass may add new fields and new methods. * Constructors: + If the superclass has no zeroary (zero parameter) constructor, the subclass must have a constructor and call the superclass's constructor on the first line. + You call the superclass's constructor with super(PARAMS) * Note: Since the superclass's methods are used, it is unlikely that an object-returning method will return an object in the subclass. * Packages are intended to protect things + Subclassing does not side-step this protection + In particular, the methods of a subclass cannot access the fields of a superclass unless those fields are declared "public" or "protected" * You can use a member of a subclass whereever you use a member of the superclass. * When a method of the subclass overrides the method of the superclass but wants to call the method of the superclass, use super.METHOD /Detour: Protection in Java and its use/ * "Everything" you describe in Java can have one of four protection levels + public: Anything can use + protected: Anything in the same package and any subclass can use it + package (no adjective/protection written): Anything in the same package can use it + private: Anything in the same class can use it * "Everything" + Classes + Methods + Fields + Constructors * Why protect? Why "What it does and not how?" + To limit the effects of changes + E.g., If I change x to xcoord and y to ycoord, I want to limit how much code breaks + E.g., If I decide to use radius and theta rather than x and y, Iwant to limit how much code breaks + To prevent others from doing "inappropriate" things to my values + E.g., Should another class be able to change my fields? If so, we sometimes get unexpected changes. /Programs Crash. Why?/ * Computational errors, such as division by 0. * External errors, such as filesystems that crash and power that goes out. * Logic errors in the program. /Design Issue: How do you deal with potential errors in a method?/ Example: (average lst) fails when the list is empty. (average lst) fails when elements of the list are not numbers. What should average do when it gets an empty list or a list of non-numbers as parameters? * Print an error message and stop the program. Crash and burn. * Return a special value for "this is wrong". In Scheme, we could use #f, NaN, original value. * Somehow ask for a new list. (Possible for human interaction, not possible for interaction with the rest of the program.) * If the preconditions are not met, it's not my fault, I can do whatever I want. For robust code, the best thing to do is to return a special value and let the caller figure out what to do. Natural calling strategy: result = call(params) if (result is special value) { } result = average(stuff); if (result == #f) { result = 1; // Careful analysis of the program suggests that 1 serves as a reasonable alternative when the list is empty. } ... result = average(stuff); while (result == #f) { pen.println("I'm sorry, that was not a reasonable value. Try again."); stuff = keyboard.readAList(); } result = average(stuff) if (result == #f) return #f; The "return a special value" is good in theory, weak in practice Typical programmers say "Assume it works for now; add the error checking code later" Sun's solution: Force programmers to deal with certain kinds of errors Methods that may fail are said to "throw exceptions" You must indicate what to do with the exception or your code won't compile. * Method that can fail public returntype methodname(xxxx) throws exception * Call to that method with recover allowed try { CODE THAT CAN FAIL } catch (Exception eryn) { RECOVER } * Call to that method with "if it fails, I fail" public returntype methodname(xxxx) throws exception { CODE THAT CAN FAIL }