Test 2 Flashcards
class declaration non static
As in the last lecture, the class declaration starts by specifying the class name public class Rectangle However, we also want to compare Rectangle objects (e.g., to sort them) public class Rectangle implements ComparableAdditional interfaces can be added in a comma-separated sequence
attributes non static
Remember that attributes are declared asaccess[static] [final] typename [= value]; We are choosing to declare private variables for the height and width, leaving them uninitializedprivate int width; private int height;
Static attributes are typically initialized when they are declared, non-static are initialized in the constructorAn attribute’s scope is the entire classThe fully qualified way to reference an attribute is with the thiskeywordthis.width or this.height However, thiscan be omitted if the result is unambiguous (e.g., attribute shadowing)
Constructors
are defined as follows: accessClassName(anyParameters)Like methods, they can be overloadedWhen a new object is created...◦Memory is allocated for the new object◦A constructor for the corresponding class is called ◦Attributes are initialized
Copy constructor
Takes an object of the same class as a parameter public ClassName(ClassName other)Creates a new object with attributes identical to the passed object Note that you do not need (and should not declare) a copy constructor for an immutable type, as the resulting object would be redundant
Constructor chaining
When a constructor invokes another constructor it is called constructor chainingTo invoke a constructor in the same class you use the thiskeyword◦If you do this then it must occur on the first line of the constructor bodyUsed to reduce code duplicationNot always feasible◦E.g., if constructor can throw exceptions
Methods
are defined as follows: access returnType signatureMethods can perform any operation on an object, but typically fall into categories: ◦Accessors – return an attribute value◦Mutators – modify an attribute value◦Obligatory – satisfy superclass or interface requirements◦Class-specific – defined by purpose of class
accessors
Allows access to (otherwise private) attribute valuesNaming convention:◦getX()for a non-Boolean attribute, named x◦isX()for a Boolean attribute, named xpublic int getWidth() { return this.width;} // similar for getHeight()
mutators
Allows modification of (otherwise private) attribute valuesNaming convention:
◦setX() for an attribute, named xpublic void setWidth(int width) { this.width = width; } // similar for setHeight()
validation using mutators
Instead of relying on preconditions, can use mutators to validate argument values
◦Throw an exception
◦Return a Boolean value For the Rectangle class, validate that any width argument is non-negative
validation with exceptions
/** Sets the width of this rectangle to the given width. @param width The new width of this rectangle.
@throws IllegalArgumentException
if width < 0.*/
public void setWidth(int width)
throws IllegalArgumentException{ if (width < 0) { throw new IllegalArgumentException(“Argument cannot be negative”); } else { this.width = width; } }
validation with boolean
/** Sets the width of this rectangle to the given width if the given width is greater than or equal to 0. Returns whether the width has been set. @param width The new width of this rectangle.@return true if width >= 0, false otherwise.*/ public boolean setWidth(int width){ boolean isSet = width >= 0; if (isSet) {this.width = width; } return isSet; }
toString method
Provides a textual representation of the Rectangle◦E.g., “Rectangle of width 1 and height 2”Default returns class name and memory addressFor the Rectangle class: public String toString() { return "Rectangle of width " + this.width + " and height " + this.height;}
equals method
Evaluate object equality using attribute values (i.e., object state) Default compares memory address (like ==)Implementing equals() is surprisingly hard ◦”One would expect that overriding equals(), since it is a fairly common task, should be a piece of cake. The reality is far from that. There is an amazing amount of disagreement in the Java community regarding correct implementation of equals().”Angelika Langer, Secrets of equals() – Part 1◦http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.htmlOur approach is consistent with many texts
instances of the same type
The implementation of equals() used in the notes and the textbook is based on the rule that an instance can only be equal to another instance of the same typeAt first glance, this sounds reasonable and is easy to implement using Object.getClass() public final Class extends Object> getClass() Returns the runtime class of an object.
instances with the same state are equal
Recall that the value of the attributes of an object define the state of the object Two instances are equal if all of their attributes are equal Recipe for checking equality of attributes1.If the attribute type is a primitive type other than float or double use ==2.If the attribute type is float use Float.compare()3.If the attribute type is double use Double.compare()4.If the attribute is an array consider Arrays.equals() 5.If the attribute is a reference type use equals(), but beware of attributes that might be null
equals()
For reference values equals() is
- Reflexive : An object is equal to itselfx.equals(x)is true
- Symmetric : Two objects must agree on whether they are equalx.equals(y)is trueif and only if y.equals(x)is true
- Transitive :If a first object is equal to a second, and the second object is equal to a third, then the first object must be equal to the thirdIf x.equals(y)is true, and y.equals(z)is true, then x.equals(z)must be true
- Consistent :Repeatedly comparing two objects yields the same result (assuming the state of the objects does not change)
- x.equals(null) is always false
compareTo()
Required if your class implements the Comparable interface (i.e., its object can be compared, order, or sorted)Compares this object with the specified object for order ◦Returns a negative integer if this object is less than ◦Returns a positive integer if this object is greater than ◦Returns zero if this object is equal to the passed oneThrows a ClassCastException if the specified object type cannot be compared to this object
comparable contract
1.The sign of the returned int must flip if the order of the two compared objects flip
if x.compareTo(y) > 0 then y.compareTo(x) < 0
if x.compareTo(y) < 0 then y.compareTo(x) > 0
if x.compareTo(y) == 0 then y.compareTo(x) == 0
2. compareTo()must be transitive
if x.compareTo(y) > 0 && y.compareTo(z) > 0 then x.compareTo(z) > 0
if x.compareTo(y) < 0 && y.compareTo(z) < 0 then x.compareTo(z) < 0
if x.compareTo(y) == 0 && y.compareTo(z) == 0then x.compareTo(z) == 0
3. If x.compareTo(y) == 0 then the signs of x.compareTo(z) and y.compareTo(z) must be the same
consistency with equals
An implementation of compareTo() is said to be consistent with equals() when if x.compareTo(y) == 0 then x.equals(y) == true and if x.equals(y) == true then x.compareTo(y) == 0
Implementing compareTo
is similar to implementing equalsTypically compare all of the attributes ◦Starting with the attribute that is most significant for ordering purposes and working your way downFor the Rectangle class, the API states that the width is used form comparison; if the widths are equal, the heights are used
hashCode
Hash codes used to uniquely (ideal) correspond to an object’s state (i.e., like a fingerprint or signature)Default uses memory address of the object Two objects with the same state should have the same hash code Hash-based containers use hash codes to organize and access elements efficiently
◦Performance increases with distinct hash codes
Poor, but legal implementation : public int hashCode() { return 1; } Better implementation : public int hashCode() { return this.getWidth() + this.getHeight(); }
Privacy leak
A mutable object that is passed to or returned from a method can be changed
Problems:
◦Private attributes become publicly accessible
◦Objects can be put into an inconsistent state
Solution: ◦Make a copy of the object and save the copyUse copy constructors
Bad
public void setDueDate(Date newDate){ dueDate = newDate; // Unsafe}
Good
public void setDueDate(Date newDate){ dueDate = new Date(newDate.getTime()); // Avoid leak }
immutable classes
A class defines an immutable type if an instance of the class cannot be modified after it is created Each instance has its own constant stateMore precisely, the externally visible state of each object appears to be constantJava examples: String, Integer (and all of the other primitive wrapper classes)Advantages of immutability versus mutabilityEasier to design, implement, and useCan never be put into an inconsistent state after creation
Recipe for Immutability
1.Do not provide any methods that can alter the state of the object Methods that modify state are called mutators
2.Prevent the class from being extended.Note that all classes extend java.lang.ObjectOne way to do this is to mark the class as final public final class PhoneNumber{ // version 0 } A final class cannot be extendedDon’t confuse final variable and final classes The reason for this step will become clear in a couple of weeks
3.Make all attributes final
Recall that Java will not allow a final attribute to be assigned to more than once
final attributes make your intent clear that the class is immutable public final class PhoneNumber{ // version 1 private final short areaCode; private final short exchange Code; private final short station Code; } Notice that the attributes are not initialized hereThat task belongs to the class constructors
4. Make all attributes privateThis applies to all public classes (including mutable classes)In public classes, strongly prefer private attributesAvoid using public attributesprivate attributes support encapsulationBecause they are not part of the API, you can change them (even remove them) without affecting any clientsThe class controls what happens to private attributesIt can prevent the attributes from being modified to an inconsistent state
5.Prevent clients from obtaining a reference to any mutable attributesRecall that final attributes have constant state only if the type of the attribute is a primitive or is immutableIf you allow a client to get a reference to a mutable attribute, the client can change the state of the attribute, and hence, the state of your immutable class
attribute caching
Involves saving an object’s characteristic, rather than recalculating it Must balance added redundancy (bad) with increased performance (good) Attribute is recalculated only when needed (i.e., when its components are modified) and returned when its accessor method is called
class invariants
A property that objects of a particular class always hold ◦E.g., a Rectangle’s width and height are always ≥ 0Must satisfy two constraints: 1.The class invariant has to be true after each public constructor invocation (provided the constructor’s precondition is also met)2.The class invariant has to be maintained by each public method invocation (provided the method’s precondition is also met)
hash tables
You can think of a hash table as being an array of buckets where each bucket holds the stored objects
To insert an object a, the hash table calls a.hashCode() method to compute which bucket to put the object into 53 0 1 2 3 … N a.hashCode() 2a b.hashCode() 0 b c.hashCode() Nc d.hashCode() Nd means the hash table takes the hash code and does something toit to make it fit in the range 0—N
search on hash table
To see if a hash table contains an object a, the hash table calls a.hashCode() method to compute which bucket to look for a in Searching a hash table is usually much faster than linear search Doubling the number of elements in the hash table usually does not noticably increase the amount of search neededIf there are nPhoneNumbers in the hash table:Best case: the bucket is empty, or the first PhoneNumber in the bucket is the one we are searching for 0 or 1 call to equals()Worst case: all n of the PhoneNumbers are in the same bucket N calls to equals()Average case: the PhoneNumber is in a bucket with a small number of other PhoneNumbersa small number of calls to equals()
static attributes
An attribute that is staticis a per-class memberOnly one copy of the attribute, and the attribute is associated with the class Every object created from a class declaring a static attribute shares the same copy of the attribute Static attributes are used when you really want only one common instance of the attribute for the class
mixing static and non static attributes
A class can declare static (per class) and non-static (per instance) attributesA common textbook example is giving each instance a unique serial numberThe serial number belongs to the instance Therefore it must be a non-static attribute How do you assign each instance a unique serial number? The instance cannot give itself a unique serial number because it would need to know all the currently used serial numbersCould require that the client provide a serial number using the constructorInstance has no guarantee that the client has provided a valid (unique) serial number The class can provide unique serial numbers using static attributesE.g. using the number of instances created as a serial number The class can provide unique serial numbers using static attributesE.g. using the number of instances created as a serial number A more sophisticated implementation might use an object to generate serial numbers
static methods
Recall that a static method is a per-class method Client does not need an object to invoke the method Client uses the class name to access the method A static method can only use static attributes of the class static methods have no this parameter because a static method can be invoked without an object Without a this parameter, there is no way to access non-static attributes Non-static methods can use all of the attributes of a class (including static ones)
Singleton patterns
A singleton is a class that is instantiated exactly once Singleton is a well-known design pattern that can be used when you need to: 1.Ensure that there is no more than one instance of a class, and 2.Provide a global point of access to the instance Any client that imports the package containing the singleton class can access the instance
one and only one
How do you enforce this?Need to prevent clients from creating instances of the singleton class privateconstructorsThe singleton class should create the one instance of itselfNote that the singleton class is allowed to call its own privateconstructorsNeed a static attribute to hold the instance
example of singleton
public class Santa { // whatever attributes you want for santa… private static final Santa INSTANCE = new Santa(); private Santa() { // initialize attributes here… } … }
global access
How do clients access the singleton instance? By using a static method Note that clients only need to import the package containing the singleton class to get access to the singleton instance Any client method can use the singleton instance without mentioning the singleton in the parameter list
lazy instantiation
Notice that the previous singleton implementation always creates the singleton instance whenever the class is loadedIf no client uses the instance then it was created needlesslyIt is possible to delay creation of the singleton instance until it is needed by using lazy instantiation
synchronizing methods
A single program can have multiple threads of execution, leading to interleaving of instructions (even on single core CPUs) CPU scheduling (which can vary from run to run) can result in two singleton objects Must ensure that the getInstance() method is executed in its entirety without interruption ◦Use synchronized keyword
one instance per state
The Java language specification guarantees that identical String literals are not duplicated // client code somewhere String s1 = "xyz";String s2 = "xyz"; // how many String instances are there?System.out.println("same object? " + (s1 == s2) ); Prints: same object? trueThe compiler ensures that identical String literals all refer to the same object A single instance per unique state
Multiton class
A singleton class manages a single instance of the class A multiton class manages multiple instances of the class What do you need to manage multiple instances? A collection of some sort How does the client request an instance with a particular state? It needs to pass the desired state as arguments to a method
Singleton
One instance
private static final Santa INSTANCE = new Santa();
Zero-parameter accessor
public static Santa getInstance()
Multiton
Multiple instances (each with unique state) private static final Map instances = new TreeMap();
Accessor needs to provide state information
public static PhoneNumber getInstance(int areaCode, int exchangeCode, int stationCode)
making a multitone
1.Multiple instances (each with unique state) private static final Map instances = new TreeMap();
2.Accessor needs to provide state informationpublic static PhoneNumber getInstance(int areaCode,
int exchangeCode, int stationCode)getInstance() will get an instance from instances if the instance is in the map; otherwise, it will create the new instance and put it in the map
- Require private constructorsTo prevent clients from creating instances on their ownclients should use getInstance()
- Require immutability of PhoneNumbers To prevent clients from modifying state, thus making the keys inconsistent with the PhoneNumbers stored in the mapRecall the recipe for immutability…
Map
A map stores key-value pairs Map Values are put into the map using the key 31 key typevalue type// client code somewhereMap m = new TreeMap; PhoneNumber ago = new PhoneNumber(416, 979, 6648); String key = "4169796648"m.put(key , ago) Values can be retrieved from the map using only the key If the key is not in the map the value returned is null32 // client code somewhere Map m = new TreeMap ; PhoneNumber ago = new PhoneNumber(416, 979, 6648);String key = "4169796648"; m.put(key , ago); PhoneNumber gallery = m.get(key ); // == ago PhoneNumber art = m.get("4169796648"); // == ago PhoneNumber pizza = m.get("4169671111"); // == null A map is not allowed to hold duplicate keysIf you re-use a key to insert a new object, the existing object corresponding to the key is removed and the new object inserted 33 // client code somewhereMap m = new TreeMap;PhoneNumber ago = new PhoneNumber(416, 979, 6648);String key = "4169796648"; m.put(key , ago); // add ago System.out.println(m);m.put(key , new PhoneNumber(416, 586, 8000)); // replaces agoSystem.out.println(m); {4169796648=(416) 979-6648}{4169796648=(416) 586-8000}
mutable keys
Note: great care must be exercised if mutable objects are used as map keys. The behaviour of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.
static factory method
Notice that Singleton and Multiton use a static method to return an instance of a classA static method that returns an instance of a class is called a static factory methodFactory because, as far as the client is concerned, the method creates an instance Similar to a constructor
Aggregation and composition
The terms aggregation and composition are used to describe a relationship between objectsBoth terms describe the has-a relationshipThe university has-a collection of departmentsEach department has-a collection of professors
Composition implies ownershipIf the university disappears then all of its departments disappearA university is a composition of departmentsAggregation does not imply ownershipIf a department disappears then the professors do not disappearA department is an aggregation of professors
Aggregation
Suppose a Person has a name and a date of birth public class Person {
private String name;
private Date birthDate;
public Person(String name, Date birthDate) { this.name = name;
this.birthDate = birthDate; }
public Date getBirthDate() {
return birthDate; } }
The Person example uses aggregation
◦Notice that the constructor does not make a copy of the name and birth date objects passed to it
◦The name and birth date objects are shared with the client
◦Both the client and the Person instance are holding references to the same name and birth date
What happens when the client modifies the Date instance?
// client code somewhere
String s = “Billy Bob”;
Date d = new Date(90, 2, 26);
// March 26, 1990Person p = new Person(s, d);
d.setYear(95);
// November 3, 1995
d.setMonth(10);
d.setDate(3);
System.out.println( p.getBirthDate() );
Because the Date instance is shared by the client and the Person instance:◦The client can modify the date using d and the Person instance p sees a modified birthDate
◦The Person instance p can modify the date using birthDate and the client sees a modified date d
Note that even though the String instance is shared by the client and the Person instance p, neither the client nor p can modify the String
◦Immutable objects make great building blocks for other objects ◦They can be shared freely without worrying about their state
aggregation example
3D videogames use models that are a three-dimensional representations of geometric data ◦The models may be represented by:
Three-dimensional points (particle systems)
Simple polygons (triangles, quadrilaterals)
Smooth, continuous surfaces (splines, parametric surfaces)
An algorithm (procedural models)
Rendering the objects to the screen usually results in drawing triangles
◦Graphics cards have specialized hardware that does this very fast
triangle aggregation
Implementing Triangle is very easyAttributes (3 Point references)◦Are references to existing objects provided by the clientAccessors◦Give clients a reference to the aggregated Points Mutators ◦Set attributes to existing Points provided by the clientWe say that the Triangle attributes are aliases
If a client gets a reference to one of the triangle’s points, then the client can change the position of the point without asking the triangle
Composition
Recall that an object of type X that is composed of an object of type Y means
◦X has-a Y object and
◦X owns the Y object
In other words 29 The X object, and only the X object, is responsible for its Y object
//////
The X object, and only the X object, is responsible for its Y object
This means that the X object will generally not share references to its Y object with clients
◦Constructors will create new Y objects
◦Accessors will return references to new Y objects ◦Mutators will store references to new Y objects
The “new Y objects” are called defensive copies
/////
If a default constructor is defined it must create a suitable Y object public X() { // create a suitable Y; for example this.y = new Y( /* suitable arguments */ ); } 31 the X object, and only the X object, is responsible for its Y object
If a copy constructor is defined it must create a new Y that is a deep copy of the other X object’s Y object public X(X other) { // create a new Y that is a copy of other.y this.y = new Y(other.getY()); }
Composition and copy constructor
What happens if the X copy constructor does not make a deep copy of the other X object’s Yobject? // don’t do this public X(X other) { this.y = other.y; } ◦Every X object created with the copy constructor ends up sharing its Y object If one X modifies its Y object, all X objects will end up with a modified Y objectWhat is this an example of? a constructor that has a Y parameter must first deep copy and then validate the Y object public X(Y y) { // create a copy of y Y copy Y = new Y(y); // validate; will throw an exception if copy Y is invalid this.checkY(copyY); this.y = copyY; }
Why is the deep copy required?
the X object, and only the X object, is responsible for its Y object
If the constructor does this
// don’t do this for composition
public X(Y y) { this.y = y; }
then the client and the X object will share the same Y objectThis is a privacy leak
Never return a reference to an attribute;
always return a deep copy public Y getY() { return new Y(this.y); }
composition and mutators
If X has a method that sets its Y object to a client-provided Y object then the method must make a deep copy of the client-provided Y object and validate it public void setY(Y y) { Y copyY = new Y(y); // validate; will throw an exception if copyY is invalid this.checkY(copyY); this.y = copyY; } If the mutator does this // don’t do this for composition public void setY(Y y) { this.y = y; } then the client and the X object will share the same Y objectThis is a privacy leak
period class
We want to implement a class that represents a period of time
◦A period has a start time and an end time
End time is always after the start time
We want to implement a class that represents a period of time
◦Has-a: Date representing the start of the time period ◦Has-a: Date representing the end of the time period
◦Class invariant: start of time period is always prior to the end of the time period
Class invariant
◦Some property of the state of the object that is established by a constructor and maintained between calls to public methods
collections as attributes
Often you will want to implement a class that has-a collection as an attribute ◦A university has-a collection of faculties and each faculty has-a collection of schools and departments ◦A molecule has-a collection of atoms ◦A person has-a collection of acquaintances ◦A student has-a collection of GPAs and has-a collection of courses ◦A polygonal model has-a collection of triangles
what does collection hold?
A collection holds references to instances
◦It does not hold the instances
Student class
A Student has-a string id
A Student has-a collection of yearly GPAs
A Student has-a collection of courses
Polygonal model class
A polygonal model has-a List of Triangles ◦AggregationImplements Iterable◦Allows clients to access each Triangle sequentiallyClass invariant ◦List never null
When using a collection as an attribute
of a class X you need to decide on ownership issues ◦Does X own or share its collection? ◦If X owns the collection, does X own the objects held in the collection?
If X shares its collection with other X instances
then the copy constructor does not need to create a new collection
◦The copy constructor can simply assign its collection
◦The text refer to this as aliasing
x owns its collection shallow copy
If X owns its collection but not the objects in the collection then the copy constructor can perform a shallow copy of the collectionA shallow copy of a collection means ◦X creates a new collection ◦The references in the collection are aliases for references in the other collection
The hard way to preform a shallow copy
The hard way to perform a shallow copy54 // assume there is an ArrayList datesArrayList sCopy = new ArrayList(); for(Date d : dates){ sCopy.add(d);}
The easy way to perform a shallow copy
// assume there is an ArrayList datesArrayList sCopy = new ArrayList(dates);
deep copy
If X owns its collection and the objects in the collection then the copy constructor must perform a deep copy of the collectionA deep copy of a collection means
◦X creates a new collection
◦The references in the collection are references to new objects (that are copies of the objects in other collection)
How to perform a deep copy57 // assume there is an ArrayList datesArrayList sCopy = new ArrayList(); for(Date d : dates){ sCopy.add(new Date(d.getTime()); } deep copy: new List created and new elements created constructor invocation creates a new object
inheritance and classes
We say that a subclass is derived from its superclassWith the exception of Object, every class in Java has one and only one superclass ◦Java only supports single inheritanceA class X can be derived from a class that is derived from a class, and so on, all the way back to Object ◦X is said to be descended from all of the classes in the inheritance chain going back to Object ◦All of the classes X is derived from are called ancestors of X
why inheritance?
A subclass inherits all of the non-private members (attributes and methods but not constructors) from its superclass ◦If there is an existing class that provides some of the functionality you need you can derive a new class from the existing class ◦The new class has direct access to the public and protected attributes and methods without having to re-declare or re-implement them ◦The new class can introduce new attributes and methods ◦The new class can re-define (override) its superclass methods
is-a
Inheritance models the is-a relationship between classesFrom a Java point of view, is-a means you can use a derived class instance in place of an ancestor class instance 8 public someMethod(Dog dog){ // does something with dog }// client code of someMethodKomondor shaggy = new Komondor();someMethod( shaggy );Mix mutt = new Mix ();someMethod( mutt );
is-a pitfalls
Is-a has nothing to do with the real worldIs-a has everything to do with how the implementer has modelled the inheritance hierarchyThe classic example:◦Circleis-a Ellipse? f Ellipse can do something that Circle cannot, then Circle is-a Ellipse is false ◦Remember: is-a means you can substitute a derived class instance for one of its ancestor instances If Circle cannot do something that Ellipse can do then you cannot (safely) substitute a Circle instance for an Ellipse instance There is no good way for Circle to support setSize(assuming that the attributes widthand height are always the same for a Circle) because clients expect setSize to set both the width and heightCan't Circle override set Size so that it throws an exception if width != height?◦No; this will surprise clients because Ellipse setSize does not throw an exception if width != heightCan't Circle override setSize so that it sets width == height?◦No; this will surprise clients because Ellipse setSize says that the width and height can be different What if there is no setSizemethod?◦If a Circle can do everything an Ellipse can do then Circle can extend Ellipse
implementing inheritance
Suppose you want to implement an inheritance hierarchy that represents breeds of dogs for the purpose of helping people decide what kind of dog would be appropriate for themMany possible attributes:◦Appearance, size, energy, grooming requirements, amount of exercise needed, protectiveness, compatibility with children, etc.
◦We will assume two attributes measured on a 10 point scaleSize from 1 (small) to 10 (giant) Energy from 1 (lazy) to 10 (high energy)
A subclass
A subclass looks like a new class that has the same API as its superclass with perhaps some additional methods and attributesInheritance does more than copy the API of the superclass ◦The derived class contains a subobject of the parent class ◦The superclass subobject needs to be constructed (just like a regular object) The mechanism to perform the construction of the superclass subobject is to call the superclass constructor A subclass looks like a new class that has the same API as its superclass with perhaps some additional methods and attributesInheritance does more than copy the API of the superclass ◦The derived class contains a subobject of the parent class ◦The superclass subobject needs to be constructed (just like a regular object) The mechanism to perform the construction of the superclass subobject is to call the superclass constructor 1.The first line in the body of every constructor must be a call to another constructor ◦If it is not then Java will insert a call to the superclass default constructor If the superclass default constructor does not exist or is private then a compilation error occurs 2.A call to another constructor can only occur on the first line in the body of a constructor 3.The superclass constructor must be called during construction of the derived class
Mix object
Mix mutt = new Mix(1, 10);
- Mix constructor starts running •Creates new Dog subobject by invoking the Dog constructor
- Dog constructor starts running •creates new Object subobjectby (silently) invoking the Objectconstructor
- Object constructor runs•sets size and energy •Creates a new empty ArrayListand assigns it to breeds
Why is the constructor call to the superclass needed?
Because Mix is-a Dog and the Dog part of Mix needs to be constructed Similarly, the Object part of Dog needs to be constructed
invoking the superclass ctor
A derived class can only call its own constructors or the constructors of its immediate superclass ◦Mix can call Mix constructors or Dog constructors ◦Mix cannot call the ObjectconstructorObjectis not the immediate superclass of Mix ◦Mix cannot call Pure Breed constructorsCannot call constructors across the inheritance hierarchy ◦Pure Breed cannot call KomondorconstructorsCannot call subclass constructors
constructors and overridable methods
If a class is intended to be extended then its constructor must not call an overridable method ◦Java does not enforce this guidelineWhy?◦Recall that a derived class object has inside of it an object of the superclass ◦The superclass object is always constructed first, then the subclass constructor completes construction of the subclass object ◦The superclass constructor will call the overridden version of the method (the subclass version) even though the subclass object has not yet been constructed
overrides methods
public class SubbyDubby extends SuperDuper{ private final Date date; public SubbyDubby() { super(); this.date = new Date(); } @Override public void overrideMe() { System.out.print("SubbyDubby overrideMe : "); System.out.println( this.date ); } public static void main(String[] args) { SubbyDubby sub = new SubbyDubby(); sub.overrideMe();} }
The programmer’s intent was probably to have the program print: SuperDuper overrideMe SubbyDubby overrideMe :or, if the call to the overridden method was intentional SubbyDubby overrideMe :SubbyDubby overrideMe :But the program prints:SubbyDubby overrideMe : nullSubbyDubby overrideMe :32 final attribute in two different states!
1.new SubbyDubby()calls the SubbyDubbyconstructor 2.The SubbyDubbyconstructor calls the SuperDuperconstructor
3.The SuperDuperconstructor calls the method overrideMewhich is overridden by SubbyDubby
4.The SubbyDubbyversion of overrideMeprints the SubbyDubbydateattribute which has not yet been assigned to by the SubbyDubbyconstructor (so dateis null)
5.The SubbyDubbyconstructor assigns date
6.SubbyDubbyoverrideMeis called by the client
Remember to make sure that your base class constructors only call final methods or private methods
◦If a base class constructor calls an overridden method, the method will run in an unconstructed derived class
methods in subclass
Methods in a subclass will often need or want to call methods in the immediate superclass ◦A new method in the subclass can call any public or protected method in the superclass without using any special syntax A subclass can override a public or protected method in the superclass by declaring a method that has the same signature as the one in the superclass ◦A subclass method that overrides a superclass method can call the overridden superclass method using the super keyword
Mix equals
Two Mix instances are equal if their Dog subobjects are equal and they have the same breeds
◦Dog equals already tests if two Dog instances are equal
◦Mix equals can call Dog equals to test if the Dog subobjects are equal, and then test if the breeds are equal
Also notice that Dog equals already checks that the Object argument is not null and that the classes are the same
◦Mix equals does not have to do these checks again
preconditions and inheritance
Precondition ◦What the method assumes to be true about the arguments passed to it Inheritance (is-a) ◦A subclass is supposed to be able to do everything its superclasses can do To strengthen a precondition means to make the precondition more restrictive // Dog setEnergy // 1. no precondition // 2. 1 <= energy // 3. 1 <= energy <= 10 public void setEnergy(int energy) { ... } 47
preconditions on overridden methods
A subclass can change a precondition on a method but it must not strengthen the precondition ◦A subclass that strengthens a precondition is saying that it cannot do everything its superclass can do48 // Dog setEnergy // assume non-final// @pre. nonepublicvoid setEnergy(int nrg) { // ... }// Mix setEnergy // bad : strengthen precond.// @pre. 1 <= nrg <= 10publicvoid setEnergy(int nrg) { if (nrg < 1 || nrg > 10) { // throws exception } // ...} Client code written for Dogs now fails when given a MixRemember: a subclass must be able to do everything its ancestor classes can do; otherwise, clients will be (unpleasantly) surprised
Postcondition
What the method promises to be true when it returnsThe method might promise something about its return value “Returns size where size is between 1 and 10 inclusive"The method might promise something about the state of the object used to call the method“Sets the size of the dog to the specified size" The method might promise something about one of its parameters To strengthen a postcondition means to make the postcondition more restrictive // Dog getSize // 1. no postcondition // 2. 1 <= this.size // 3. 1 <= this.size <= 10 public int getSize() { ... }
subclass and postconditions
A subclass can change a postcondition on a method but it must not weaken the postcondition ◦A subclass that weakens a postcondition is saying that it cannot do everything its superclass can do52 // Dog getSize // // @post. 1 <= size <= 10publicint getSize(){ // ... }// Dogzilla getSize// bad : weaken postcond.// @post. 1 <= sizepublicint getSize(){ // ... } Dogzilla: a made-up breed of dog that has no upper limit on its size Client code written for Dogs can now fail when given a Dogzilla Remember: a subclass must be able to do everything its ancestor classes can do; otherwise, clients will be (unpleasantly) surprised53 // client code that assumes Dog size <= 10public String sizeToString(Dog d) { int sz = d.getSize(); String result = ""; if (sz < 4) result = "small"; else if (sz < 7) result = "medium"; else if (sz <= 10) result = "large"; return result; }
exceptions
All exceptions are objects that are subclasses of java.lang.Throwable You can define your own exception hierarchy ◦Often, you will subclass Exception A method that claims to throw an exception of type X is allowed to throw any exception type that is a subclass of X ◦This makes sense because exceptions are objects and subclass objects are substitutable for ancestor classes // in Dogpublic void someDogMethod() throws DogException{ // can throw a DogException, BadSizeException, // NoFoodException, or BadDogException} A method that overrides a superclass method that claims to throw an exception of type Xmust also throw an exception of type X or a subclass of X◦Remember: a subclass promises to do everything its superclass does; if the superclass method claims to throw an exception then the subclass must also // in Mix@Overridepublic void someDogMethod() throws DogException{ // ...}
Whats right?
In Mix
@Overridepublic void someDogMethod() throws BadDogException +
@Overridepublic void someDogMethod() throws Exception -
@Overridepublic void someDogMethod() -@Overridepublic void someDogMethod() throws DogException, IllegalArgumentException +
inheritance recap
Inheritance allows you to create subclasses that are substitutable for their ancestors ◦Inheritance interacts with preconditions, postconditions, and exception throwing Subclasses◦Inherit all non-private features ◦Can add new features ◦Can change the behaviour of non-final methods by overriding the parent method◦Contain an instance of the superclass Subclasses must construct the instance via a superclass constructor
polymorphism
Inheritance allows you to define a base class that has attributes and methods ◦Classes derived from the base class can use the public and protected base class attributes and methods Polymorphism allows the implementer to change the behaviour of the derived class methods
late binding
Polymorphism requires late binding of the method name to the method definition
◦Late binding means that the method definition is determined at run-time66 obj.toString() non-static method run-time type of the instance obj
Dog lady = new CockerSpaniel();
The declared type of an instance determines what methods can be used
◦The name lady can only be used to call methods in Dog
◦lady.someCockerSpanielMethod() won’t compile
The actual type of the instance determines what definition is used when the method is called ◦lady.toString() uses the CockerSpaniel definition of toString
abstract classes
Sometimes you will find that you want the API for a base class to have a method that the base class cannot define ◦E.g. you might want to know what a Dog's bark sounds like but the sound of the bark depends on the breed of the dog You want to add the method bark to Dog but only the subclasses of Dog can implement bark ◦E.g. you might want to know the breed of a Dog but only the subclasses have information about the breed You want to add the method getBreedto Dog but only the subclasses of Dog can implement getBreed Sometimes you will find that you want the API for a base class to have a method that the base class cannot define ◦E.g. you might want to know the breed of a Dog but only the subclasses have information about the breedYou want to add the method getBreedto Dogbut only the subclasses of Dog can implement getBreed If the base class has methods that only subclasses can define and the base class has attributes common to all subclasses then the base class should be abstract ◦If you have a base class that just has methods that it cannot implement then you probably want an interfaceAbstract : (Dictionary definition) existing only in the mindIn Java an abstract class is a class that you cannot make instances of
abstract class
An abstract class provides a partial definition of a class◦The subclasses complete the definition An abstract class can define attributes and methods◦Subclasses inherit theseAn abstract class can define constructors ◦Subclasses can call theseAn abstract class can declare abstract methods◦Subclasses must define these (unless the subclass is also abstract)
abstract methods
define, zero or more abstract methodsThe base class is saying “all Dogs can provide a String describing the breed, but only the subclasses know enough to implement the method
non abstract subclasses
The non-abstract subclasses must provide definitions for all abstract methods
◦Consider getBreed in Mix
purebreed
A purebreed dog is a dog with a single breed ◦One String attribute to store the breed Note that the breed is determined by the subclasses ◦The class PureBreed cannot give the breedattribute a value ◦But it can implement the method getBreed The class PureBreeddefines an attribute common to all subclasses and it needs the subclass to inform it of the actual breed ◦PureBreed is also an abstract class The subclasses of PureBreedare responsible for setting the breed
static attributes in inheritance
Static attributes behave the same as non-static attributes in inheritance ◦Public and protected static attributes are inherited by subclasses, and subclasses can access them directly by name ◦Private static attributes are not inherited and cannot be accessed directly by nameBut they can be accessed/modified using public and protected methods The important thing to remember about static attributes and inheritance ◦There is only one copy of the static attribute shared among the declaring class and all subclasses Consider trying to count the number of Dog objects created by using a static counter
There is only one copy of the static attribute shared among the declaring class and all subclasses
There is only one copy of the static attribute shared among the declaring class and all subclasses ◦Dogdeclared the static attribute◦Dogincrements the counter everytime its constructor is called◦Mixinherits and shares the single copy of the attribute◦Mixconstructor correctly calls the superclass constructor Which causes numCreatedto be incremented by Dog◦Mixconstructor then incorrectly increments the counter
count instances
Suppose you want to count the number of Doginstances and the number of Mixinstances◦Mixmust also declare a static attribute to hold the countSomewhat confusingly, Mixcan give the counter the same name as the counter declared by Dog public class Mix extends Dog { // other attributes... private static int numCreated = 0; // bad style public Mix() { super(); // will increment Dog.numCreated // other Mix stuff... numCreated++; // will increment Mix.numCreated }
hiding attributes
Note that the Mixattribute numCreatedhas the same name as an attribute declared in a superclass ◦Whenever numCreatedis used in Mix, it is the Mixversion of the attribute that is usedIf a subclass declares an attribute with the same name as a superclass attribute, we say that the subclass attribute hides the superclass attribute◦Considered bad style because it can make code hard to read and understandShould change numCreated to numMixCreatedin Mix There is a big difference between calling a static method and calling a non-static method when dealing with inheritanceThere is no dynamic dispatch on static methods
There is no dynamic dispatch on static methods
Because the declared type of mutt is Dog, it is the Dog version of getNumCreatedthat is called Because the declared type of shaggy is Dog, it is the Dog version of getNumCreated that is called Notice that Mix.getNumCreatedand Komondor.getNumCreatedwork as expected If a subclass declares a static method with the same name as a superclass static method, we say that the subclass static method hides the superclass static method ◦You cannot override a static method, you can only hide it ◦Hiding static methods is considered bad form because it makes code hard to read and understand The client code in WrongCountillustrates two cases of bad style, one by the client and one by the implementer of the Doghierarchy1.The client should not have used an instance to call a static method2.The implementer should not have hidden the static method in Dog
Interfaces
Recall that you typically use an abstract class when you have a superclass that has attributes and methods that are common to all subclasses ◦The abstract class provides a partial implementation that the subclasses must complete ◦Subclasses can only inherit from a single superclass If you want classes to support a common API then you probably want to define an interface In Java an interface is a reference type (similar to a class) An interface says what methods an object must have and what the methods are supposed to do ◦I.e., an interface is an API An interface can contain only ◦Constants ◦Method signatures ◦Nested types (ignore for now) There are no method bodiesInterfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces public interface Comparable{ int compareTo(T o);}
interfaces already seen
public interface Iterable { Iterator iterator(); } public interface Collection extends Iterable { boolean add(E e); void clear(); boolean contains(Object o); // many more method signatures…}
public interface List extends Collection { boolean add(E e); void add(int index, E element); boolean addAll(Collection extends E> c); // many more method signatures…}
Decide on a name Decide what methods you need in the interfaceThis is harder than it sounds because… ◦Once an interface is released and widely implemented, it is almost impossible to changeIf you change the interface, all classes implementing the interface must also change
function interface
In mathematics, a real-valued scalar function of one real scalar variable maps a real value to another real value
creating interface
Decide on a name
◦DoubleToDoubleFunction
Decide what methods you need in the interface
◦double at(double x)◦double[] at(double[] x)
public interface DoubleToDoubleFunction{ double at(double x); double[] at(double[] x); }
class that implements interface
A class that implements an interface says so by using the implements keyword ◦Consider the function f (x) = x public class Square implements DoubleToDoubleFunction{ public double at(double x) { return x * x; } public double[] at(double[] x) { double[] result = new double[x.length]; for (int i = 0; i < x.length; i ++) { result[i] = x[i] * x[i]; } return result; } }
implementing multiple interfaces
Unlike inheritance where a subclass can extend only one superclass, a class can implement as many interfaces as it needs to public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, Serializable