Polymorphism
-
Liskov Substitution Principle
An instance of type T can be replaced by an instance of type S
if
S is a subtype of T.
public interface GasFueled{}
public interface Electric{}
public class Vehicle{}
// subtype of Vehicle
public class FordTaurus extends Vehicle implements GasFueled{}
// subtype of Vehicle
public class TeslaS extends Vehicle implements Electric{}
FordTaurus taurus = new FordTaurus();
Vehicle rental = taurus;
TeslaS snazzy = new TeslaS();
rental = snazzy; // All of these are legal;
-
Polymorphic Program design
-
Most methods rely on provided interfaces, rather than underlying implementations
-
Object fields are accessed through getters/setters
-
Things that don’t behave polymorphically
-
field accesses (eg: `Parent p = new Child(); p.x;`)
-
Static methods
-
Things that don’t behave polymorphically
//: polymorphism/FieldAccess.java
// Direct field access is determined at compile time.
class Soup {
public int field = 0;
public int getField() { return field; }
}
class Stew extends Soup {
public int field = 1;
public int getField() { return field; }
public int getSuperField() { return super.field; }
}
-
Field Access
public class FieldAccess {
public static void main(String[] args) {
Soup soup = new Stew(); // Upcast
System.out.println("soup.field = " + soup.field +
", soup.getField() = " + soup.getField());
Stew sub = new Stew();
System.out.println("sub.field = " +
sub.field + ", sub.getField() = " +
sub.getField() +
", sub.getSuperField() = " +
sub.getSuperField());
}
} /* Output:
soup.field = 0, soup.getField() = 1
sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0
*///:~ wha?
-
Generics
-
Generics
- Generics allow type flexibility in code.
- Allows for behavior independent of type. (like a LIFO “stack”)
- Generic type indicated with
<T>or<K, V>usually - Compiler replaces generic types with given type (eg:
ArrayList<String>())
-
Generics - a FIFO Queue
- queue: a data structure that allows for FIRST IN, FIRST OUT.
- this is a thought experiment, just imagine having this thing…
- Queue s = new Queue(); give you a “queue for waiting objects”
- s.append(object1); s.append(object2);
- when you s.next(); you get object1,
- if you do it again - s.next(); you get object2
-
if you do a s.next(); again, you maybe get an error or a the null object
- imagine a Queue of Persons at DMV. “standing in line”
-
Hmm.
- BUT how to we make this generic enough to use for anything: Cars at a CarWash
- We don’t want to have PersonQueue, CarQueue, etc.
- think of all the copied code, duplicates, a different class for every kind of object…
- if you’re thinking UGH, what’s that code smell?
- you’re starting to understand
-
Queue
this is an imaginary example…
// Pretend Queue has a add() method and a next() method.
Queue personQueue = new Queue<Person>(); // this queue is for persons
personQueue.add(joe); // joe starts standing in line
currentPerson = personQueue.next(); // "Next!" person being serviced
Queue carWashQueue = new Queue<Vehicle>(); // this queue tracks cars to be washed
carWashQueue.add(teslaS);
-
Terms
- Parameterized Type
- Generic Type
- Type Inference
-
Examples of generic Types
- List (ArrayList, LinkedList, etc)
List carWashQueue = new ArrayList<Vehicle>(); - Map (HashMap, TreeMap, etc)
Map carsWeSell = new HashMap<String,Vehicle>(); carsWeSell.put("Tesla S", teslaS)
-
Primitive types cannot be type parameters
Example:
// This will not compile!!!!
public class Main{
public static void main(String[] args){
ArrayList<int> primitiveArrayList = new ArrayList<>();
}
}
-
The solution? Wrapper classes!
public class Main{
public static void main(String[] args){
ArrayList<Integer> pg = new ArrayList<>();
}
}
-
Primitives and autoboxing
public static void main(String[] args){
int x, y;
x = 5;
ArrayList<Integer> box = new ArrayList<>();
box.add(x);
y = box.get(0);
System.out.println(y);
- Your primitives become Objects
-
Enumeration Classes
public enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };
- The type defined by this declaration is actually a class (a singleton class, actually)
- You never need to use equals for values of enumerated types. Simply use == to compare them.
- Because it’s a singleton class of singletons
-
Enumeration Classes
- You can add constructors, methods, and fields to an enumerated type.
public enum Size
{
SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");
private String abbreviation;
private Size(String abbreviation) { this.abbreviation = abbreviation; }
public String getAbbreviation() { return abbreviation; }
}
-
Enumeration Classes
- All enumerated types are subclasses of the class Enum.
- They inherit a number of methods from that class.
`Size.SMALL.toString()` gives "S"
conversely
`Size s = Enum.valueOf(Size.class, "SMALL");`
`Size.MEDIUM.ordinal()` gives a 0-based index (1)... XL is (3)...
-
Reflection
-
Reflection basics
java.lang.reflectpackage contains classes for examining code at runtime- It is NOT to be used by the likes of You (OR Me!!)
- allows the manipulation of code at runtime (Run Away Now!)
- only Coding Super Heros use it for arcane and dangerous purposes
- No, I am not kidding.
-
Reflection basics
java.lang.reflectpackage contains classes for examining code at runtimeConstructor,Method, andFieldclasses represent constructors, methods, and fieldsClassobjects providegetFields(),getMethods()andgetConstructors()methods
-
The Class Class
- Well, a class has to be in the Java data model, yeah?
- Used for modeling classes
- A blueprint for other Classes
- Contains info about classes
-
A Class Object
- One for every class in your program
- Used for creating objects
- Contains info about the class of object it Constructs
-
Class Object Creation
- Created by the ClassLoader
- Right Here There Be Dragons
- Created on first reference of a static member of the class
-
Getting a Class object
Object.getClass()on an instance of the desired class- Class literal (eg:
Object.classorString.class) Class.forName(String className)eg:Class.forName("java.lang.String")
-
Checking the class of an object
instanceofkeyword - requires name of class at compile timeisInstance()method - allows dynamic checking- class object equality (
==or.equals())
-
Example
String str = "Hello";
If used in a conditional:
( str instanceof String ) //true
( Object.class.isInstance(str) ) // true
( str.getClass() == String.class )// true
( str.getClass() == Object.class ) // false
( str.getClass().equals(Object.class) ) //false
-
Useful Class object methods
getName(),getSimpleName(),getCanonicalName()newInstance()cast(),getSuperclass()
-
Resources
-
