| AnImprovedInheritingStringSet.java |
package lectures.inheritance;
import util.annotations.WebDocuments;
/**
* Again first study and run the program and try to understand what
* it does on your own.
*
* It declares and defines a method that is already inherited from its superclass's
* superclass: addElement(). The @Override annotation indicates this fact.
*
* As the name indicates, this method overrides (replaces) the inherited method
* for its instances.
*
* However, the overridden method can still be accessed using the "super" prefix.
*
*/
@WebDocuments({"Lectures/Inheritance.pptx", "Lectures/Inheritance.pdf", "Videos/Inheritance.avi"})
public class AnImprovedInheritingStringSet extends AnInheritingStringDatabase // extending an extended class
implements InheritingStringDatabase { // same interface as implemented by the superclass
public AnImprovedInheritingStringSet() {
super();
// super.super();
uselessVariable = 1;
// System.out.println("AnInheritingStringSet constructor called");
// super();
}
/*
* Redeclaration of inherited addElement()
*/
@Override
public void addElement(String element) {
/*
* Set break point below and step over until you reach super.addElement()
*/
if (!member(element)) { // add only if the element is not a member
/*
* click on addElement below and hit F3 to see where the call
* on super is defined. *
*
*
*/
super.addElement(element);
/*
* what if we called addElement without super? *
*/
// addElement(element);
}
}
/*
* Useless re-declaration, does nothing useful besides show
* another form of overriding
*/
// @Override
// protected boolean isFull() {
// /*
// * Click on the name isFull() and hit CTRL-SHIFT_G (or right click
// * menu, select References->Project) to see which method calls it.
// *
// * Set breakpoint below and debug-run.
// *
// * When the program breaks look at the stack to see which method calls it and
// * where the method is declared
// */
// System.out.println ("isFull called in Set");
// return super.isFull();
// }
public int size() {
System.out.println ("Set size() called");
return super.size();
}
public static void main (String[] args) {
InheritingStringDatabase aStringSet = new AnImprovedInheritingStringSet();
System.out.println (aStringSet.size()); // size() is implemented in ABaseStringHistory
// StringDatabase aStringSet = new AStringDatabase();
/*
* click on manipulateDatabase and hit F3 to see where the call is defined
*/
manipulateDatabase(aStringSet);
/*
* What if we called the static manipulateDatabase with "super"?
* Is that legal in Java? Try uncommenting this to see.
*/
// super.manipulateDatabase(aStringSet);
}
}
/*
.
*/
/*
*
* Set a break point at the start of addElement and Step Over (F6) the
* statements to see which path is taken when main is called for each added
* element.
*
*
* COLLECTIONS
*
* Adding an item a second time to an instance of AnInheritingStringSet
* results in:
* (a) an exception.
* (b) the addition being ignored.
* (c) a duplicate item.
*
* INHERITING ANCESTOR METHODS
*
* Look at the call to size() in main.
*
* If object a is an instance of class C, and C is a subclass of E, and E
* is a subclass of F, then it is possible to invoke on a:
* (a) only the methods implemented in C.
* (b) only the methods implemented in C and E.
* (c) only the methods implemented in E.
* (d) methods implemented in C, E and F.
*
* REDECLARING ANCESTOR METHODS
*
*
* In the following 8 questions, assume c is an instance of C,
* e is an instance of E, C is a subclass of E,
* and both C and E define a method header m.
*
* (T/F) It is illegal to call m on c.
*
* (T/F) It is illegal to call m on e.
*
* (T/F) Calling m on c results in call of the implementation of m in C.
*
* (T/F) Calling m on c results in call of the implementation of m in E.
*
* (T/F) Calling m on e results in call of the implementation of m in C.
*
* (T/F) Calling m on e results in call of the implementation of m in E.
*
* (T/F) Class C can call the implementation of m in E.
*
* (T/F) Class E can call the implementation of m in C.
*
* Uncomment the re-declaration of the isFull() method and follow the
* instructions in it.
*
* (T/F) A method in superclass can call an overriding method in the subclass.
*
* Can the addElement() method in ABaseStringHistory call the member() method
* in AnInheritingStringSet? Try it if you cannot answer the question.
*
* (T/F) A method in a superclass can call a non-overriding method in the subclass.
*/
/*
*
* CLASS OBJECT
*
* Go to the definition of toString() in ABaseStringHistory.
*
* Comment out the current return statement and uncomment the one below it,
* which uses super.toString().
*
* ABaseStringHistory does not explicitly extend any class.
*
* To which class is super referring?
*
* Set a breakpoint at the new return statement.
*
* Debug-Run the program again. When you stop at the break point,
* and step into (F5) the super call in the return statement.
*
* In which class do you land? (You may not be able to see the source code of
* the class if you do not have a jdk installed, but you should be able
* to see the name of the class in Eclipse.)
*
* Which is true:
* (a) The predefined class, Object, is the immediate superclass of any class
* that does not explicitly extend a class.
* (b) The predefined class, Class, is the immediate superclass of any class
* that does not explicitly extend a class.
*
* (T/F) The method toString() is implemented in the class Object.
*
* Look at the stack of calls in the Debug window.
*
* You can keep doing step-return (F7) until you hit the main class.
*
* Which statement in the main class led to the call of toString()? (If you were doing
* step-return the whole way, you will land at the line following that statement)
*
* (T/F) System.out.println(o) calls the toString() method on o.
*
* Comment out the super.toString() call and uncomment the original
* when you are done.
*
*/
/*
*
* REDECLARING VARIABLES
*
* Uncomment the declarations of the "size" variable in AnInheritingStringDatabase.
*
* Now we have two declarations of this variable,
*
* Run that program again and look at the output - the member() and removeElement() no
* longer work properly.
*
* Can you explain why?
*
* Set a break point at the start of the addElement() method in ABaseStringHistory.
*
* Set a breakpoint also on at the start of the indexOf method in AnInheritingStringDatabase.
* When the program stops at the addElement() method, hover over the
* value of the size variable referenced in the method.
*
* What value does it have when the method finishes?
*
* Press F8 to resume the program, until you hit the breakpoint in indexOf().
*
* When the program stops in the indexOf() method, hover over the size
* variable in the method declaration.
*
* What value is it at the start of the method?
*
* Can you explain why it is different? Look at the variables window in the debugger
* at the variables of the instance of AnInheritingStringDatabase (under "this").
*
* How many size variables does it have and what are their values?
*
* Comment out the duplicate size variable declaration and
* debug-run the program again.
*
* When the program stops at indexOf, hover over the size
* variable declaration again in the method
* and look at its value again.
* Will you ever re-declare a variable again in a subclass?
*
* In the following 6 questions, assume c is an instance of C,
* e is an instance of E, C is a subclass of E,
* and both declare a variable v.
*
* (T/F) It is illegal for C to declare v.
*
* (T/F) c has a single variable named v.
*
* (T/F) c has multiple variables named v.
*
* (T/F) Methods declared in class C refer to the variable defined in C.
*
* (T/F) Methods declared in class C refer to the variable defined in E.
*
* (T/F) Methods declared in class E refer to the variable defined in E.
*
*/
/*
* PRIVATE VS PROTECTED VS DEFAULT ACCESS
*
* For this part, you need to know to look for compile errors in classes
* in this package and the package lectures.inheritance.extra.
*
* You will play with the access of the variable "uselessVariable" declared in
* class ABaseStringHistory by commenting and uncommenting appropriate
* alternate declarations.
*
* In reaction to changes to this access, you will determine in which classes
* (in these two packages) compile errors arise, indicating that the variable
* is no longer visible.
*
* You can go to the declaration of uselessVariable and press CTRL SHIFT G
* to see all of its references, or place your cursor in it, right-click and
* select References->Workspace.
*
* The variable is accessed in the several places. It is accessed in the three
* classes we have seen so far, all of which are in this package.
*
* It is also accessed in AnIndependentClassInSamePackage, declared in this
* package, which is not a subclass of ABaseStringHistory.
*
* In addition, it is accessed in
* lectures.inheritance.extra.AnObservableStringHistory and
* lectures.inheritace.extra.AnIndependentClassInAnotherPackage. The former is
* a subclass of AABaseStringHistory while the latter is not.
*
* Currently the access is public, which makes the variable visible in all
* classes in which it is accessed.
*
* Change the access to private, protected, and default, and observe the errors.
* After each change, save the file so that Java rebuilds the project and you see
* the errors.
*
* A class C can access private variables of class D only if:
* (a) C and D are the same.
* (b) C is a subclass of D (directly or indirectly).
* (c) C is in the same package as D.
* (d) none of the above
*
* A class C can access protected variables of class D only if:
* (a) C is a subclass of D (directly or indirectly).
* (b) C is in the same package as D.
* (c) C is a subclass of D (directly or indirectly) or C is in
* the same package as D
* (d) C and D are the same
*
* A class C can access variables declared in class D with default access only if:
* (a) C and D are the same.
* (b) C is a subclass of D (directly or indirectly).
* (c) C is in the same package as D.
* (d) C is a subclass of D (directly or indirectly) or C is in
* the same package as D.
*
* Return the variable to public access once you're done.
*
* CONSTRUCTORS AND SUBCLASSING
*
* Uncomment the println() calls in the parameterless constructor in
* ABaseStringHistory, AnInheritingStringDatabase, and AnInheritingStringSet
* and run this program and observe the output.
*
* If C is a subclass of E, and an object c of type C is instantiated, then:
* (a) a constructor of only C is called.
* (b) a constructor of only E is called.
* (c) a constructor of C and E are called.
*
* Comment out the first call to super() and uncomment the first call to
* super(2) in the constructor of AnInheritingStringDatabase.
*
* Run the program or use F3 to go to the definition of super(2).
*
* (T/F) A constructor in a class can determine which overloaded
* constructor of its superclass is called by providing appropriate parameters to
* a super call that does not specify a method name.
*
* Comment out the first call to super(2) and uncomment the second one.
* What happens?
*
* Comment out the super(2) call.
*
* (T/F) A super() call can be invoked anywhere in a constructor.
*
* Uncomment the super(2) call in the clear() method. What happens?
*
* (T/F) A superclass constructor can be called from any method of a subclass.
*
* Comment out this super(2) call.
*
* Now you have no super calls in AnInheritingStringDatabase.
*
* Run the program.
*
* Is the constructor of ABaseStringHistory called? If so, which one?
*
* Comment out the parameterless constructor in ABaseStringHistory and go to
* AnInheritingStringDatabase. What happened?
*
* If no super() call is made in a constructor:
* (a) an exception is thrown.
* (b) no superclass constructor is called.
* (c) a call to the parameterless super constructor is automatically added as
* the first statement in the constructor.
*
* Uncomment the parameterless constructor in ABaseStringHistory.
*
* Comment out the entire constructor in AnInheritingStringDatabase so
* we have no constructor in this class.
*
* Run the program. Is the superclass constructor called?
*
* (T/F) If a class has no constructor, then Java inserts into its object code
* a constructor with no parameters that makes a call to a constructor with
* no parameters in its superclass.
*
*
* ORDER OF INITIALIZATION
*
* To really understand what is going on, put a break point on the first statement of
* the constructor in AStringSet and use f5 (Step into) to trace the path to the constructor
* in ABaseStringHistory noting the order in which the variables and constructors are called.
* Step over (F6) any println calls so that you do not get pulled into that code (if you
* accidentally step into a println call, just step return- F8).
*
* What is the order of initialization in this process?
*
*/