| AnInheritingStringSet.java |
package lectures.inheritance;
import util.annotations.WebDocuments;
/**
* This class illustrates the concept of sets, method overriding.
*/
@WebDocuments({"Lectures/Inheritance.pptx", "Lectures/Inheritance.pdf", "Videos/Inheritance.avi"})
public class AnInheritingStringSet extends AnInheritingStringDatabase // extending an extended class
// comment out the next line when asked
implements InheritingStringDatabase // same interface as implemented by the superclass, need not be explicitly mentioned
{
/*
* Since AnInheritingStringSet extends AnInheritingStringDatabase,
* and AnInheritingStringDatabase extends ABaseStringHistory,
* AnInheritingStringSet is a direct/child/immediate subclass/subtype of AnInheritingStringDatabase
* an indirect/descendant subclass/subtype of ABaseStringHistory, and a subclass/subytype
* of both AnInheritingStringDatabase and ABaseStringHistory.
*
*
* Similarly, AnInheritingStringDatabase is a direct/parent/immediate superclass of
* AnInheritingStringSet, ABaseStringHistory is an indirect/ancestor superclass
* of AnInheritingStringSet, both AnInheritingStringDatabase and ABaseStringHistory
* are superclasses/supertypes of AnInheritingStringSet, and AnInheritingStringDatabase
* is the closer superclass.
*
*
*
* If class A extends B, and B is a subclass of C then A is a:
* (a) subclass of B
* (b) direct/child subtype of B.
* (c) direct/child subtype of C.
* (d) indirect/descendant subtype of B.
* (e) indirect/descendant subtype of C.
* (f) closer subclass of C (in comparison to B)
*
*/
/*
* Look at the interface of this class:
*
* (T/F) If class C1 implementing I1 is a subclass of C2 implementing I2, then I2
* must be a subtype of I1.
*/
public AnInheritingStringSet() {
super();
// super.super();
uselessVariable = 1;
// System.out.println("AnInheritingStringSet constructor called");
// super();
}
@Override
public void addElement(String element) {
/*
* Set break point below when asked.
*/
if (isFull()) {
System.out.println("Adding item to a full history");
} else if (!member(element)) { // add only if the element is not a member
super.addElement(element);
/*
* what if we called addElement without super? *
*/
// addElement(element);
}
}
/*
*
* Click on the addElement in super.addElement() and hit Command/CTRL-Click to see
* where the call on super is defined.
*
* super.addElement() in AnInheritingStringSet refers to an addElement() method
* in:
* (a)AnInheritingStringSet
* (b)the direct/parent superclass of AnInheritingStringSet.
* (c)an indirect/ancestor superclass of AnInheritingStringSet.
*
* The addElement() methods in AnInheritingStringSet and ABaseStringHistory
* have the same:
* (a) name
* (b) parameter(s)
* (c) header
*
* (T/F) A class can implement two methods with the same header.
* (T/F) A class and a superclass can implement two methods with the same header.
*
* Uncomment the addElement() method in the direct superclsas of this class.
*
* Click again on the addElement in super.addElement() and hit Command/CTRL-Click to see
* where the call on super is defined.
*
* Comment out the method again in the direct superclass.
*
* If a method with header m is implemented in class A, its direct super class
* B, and its indirect super class, C, then call to super.m() in A calls the
* implementation of m() in:
* (c) A
* (b) B
* (c) C
*
* (T/F) The call super.m() in class C refers to the implementation of m in the:
* (a) closest superclass of C that implements m.
* (b) furthest superclass of C that implements m.
*/
public static void main (String[] args) {
InheritingStringDatabase aStringSet = new AnInheritingStringSet();
System.out.println (aStringSet.size()); // size() is implemented in ABaseStringHistory
// StringDatabase aStringSet = new AStringDatabase();
/*
* click on manipulateDatabase and hit F3/CTRL/CMD Click to see where
* the call is defined
*/
/*
* set break point
*/
manipulateDatabase(aStringSet);
/*
* What if we called the static manipulateDatabase with "super"?
* Is that legal in Java? Try uncommenting this to see.
*/
// super.manipulateDatabase(aStringSet);
}
}
/*
* INHERITING ANCESTOR METHODS
*
* Based on the call to size() in main:
*
* If object, O, is an instance of C, then it is possible to invoke on O public
* methods declared in:
* (a) C,
* (b) C's direct superclass
* (c) C's indirect superclasses
*
*/
/*
*
* SETS
*
* Run the main method, look at the output, and study the addElement() method
* defined here.
*
* Adding an item a second time to an instance of AnInheritingStringDatabase
* results in:
* (a) an error.
* (b) the addition being ignored.
* (c) a duplicate item.
*
* Adding an item a second time to an instance of AnInheritingStringSet
* results in:
* (a) an error.
* (b) the addition being ignored.
* (c) a duplicate item.
*/
/*
* REDECLARING ANCESTOR METHODS
*
* Set the break point in main and use Step Into (F5) and Step Over (F6) to see
* which path is taken when main is called for each added element.
*
* If O is an instance of A, and mutltiple implementations of m() exist in the super type
* hierarchy, then calling m() on O:
*
* (a) gives a compile time error.
* (b) gives a runtime error.
* (c) calls all implementations of m() - the one in A and the ones in A's superclasses.
* (d) calls the implementation of m() in the furthest superclass of A.
* (e) calls the implementation of m() in A, if it exists, or the
* implementation of m() in the closest superclass of A
*
* (T/F) A subclass can control the nature of inheritance by overriding an
* inherited method, that is, replacing the implementation of an inherited with
* its own one.
*
*
* If O is an instance of A, and a method with header m() is implemented in
* A and one or more of its superclasses, then it *not* possible for a method in A to call the
* implementation of m() in:
*
* (a) A
* (b) any superclass of A.
* (c) none of the above
*
*
* Comment out the implements clause in this class. Does the line:
*
* InheritingStringDatabase aStringSet = new AnInheritingStringSet();
*
* in the main method give an error?
*
* (T/F) A class is implicitly considered to implement the interfaces implemented by its superclasses.
* (T/F) A subclass can control the nature of inheritance by disabling the invocation
* of an inherited method declared in an interface of a superclass.
*
*/
/*
* ROOT SUPERCLASS
*
* 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.)
*
* Stepping into super.toString() in ABaseStringHistory
* (a) gives an error
* (b) executes the toString() method in class Object
* (c) does nothing
*
* (T/F) The method toString() is implemented in the class Object.
*
* A class that has no superclass is a root superclass.
*
* Which is true:
* (a) The predefined class, Object, is the immediate superclass of any class
* that does not explicitly extend a class.
* (c) A class that does not explicitly extend any class is a root superclass.
*
*
* 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)
*
* System.out.println(o) calls
* the toString() method on o.
* the println() method on o.
* getter() methods of o.
* none of the above
*
* 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, one in AnInheritingStringDatabase
* and one in its superclass.
*
* Run that program again and look at the output.
*
* Redeclaring the size variable in AnInheritingStringDatabase causes the following
* methods to not work:
* a) member()
* b) removeElement()
* c) addElement()
* d) none of the above.
*
* Set a break point at the start of the addElement() method in ABaseStringHistory.
*
* Set a breakpoint also on at the start of the shiftUp 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?
*
* (T/F) At the end of the addElement() method of ABaseStringHistory, the
* value of the size variable referenced by the method is 0.
*
* Press F8 to resume the program, until you hit the breakpoint in shiftUp().
*
* When the program stops in the shiftUp() method, hover over the size
* variable in the method body.
*
* What value is it at the start of the method?
*
* (T/F) At the start of the shiftUp() method of AnInheritingStringDataabsese the
* value of the size variable referenced by the method is 0 when
* AnInheritingStringDatase redeclares the variable.
*
* 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?
*
* The physical structure of AnInheritingStringDatabase has:
* (a) only one size variable,
* (b) two size variables, whose values are always the same.
* (c) two size variables, whose values can diverge.
*
* (T/F) The physical structure of an object cannot have
* two variables with the same name.
*
* (T/F) Methods declared in class C can refer to variables declared in its subclasses.
*
*
*
* Comment out the duplicate size variable declaration.
*
* Will you ever re-declare a variable again in a subclass?
*
*/
/*
* 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.
*
* 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).
*
* if you reach class Object, Step return (F7)
*
* If you reach an initializing variable declaration such as
* int uselessVariable2 = 0;
* Step over (F6)
*
* Which are true:
*
* The initialization declaration of AnInheritingStringDatabase
* AnInheritingStringDatabase is executed:
* (a) before the initializing declarations in
* ABaseStringHistory is executed.
* (b) before the constructor of AnInheritingStringDatabase is executed
* (c) before the constructor of ABaseStringHistory is executed.
*
* (T/F) Java executes the constructor of a class after before executing the constructors of its superclasses.
* (T/F) Java executes the initialization declaration of a class before executing its constructors.
* (T/F) Java executes the initialization declaration of a class before executing the initialization
* declarations of its superclassses.
* (T/F) Java executes the initialization declaration of a class before executing the constructors of its superclasses.
*
* Look carefully at the initialization declarations of anotherUselessVariable
*
* (T/F) The initialization declaration of a class can refer to a variable
* declared in a superclass.
*
* (T/F) The initialization declaration of a class should be executed after the variables of its
* superclasses have been initialized by the superclass declarations or constructors.
*/
/*
* Next class StringHistoryFactory
*/