Extends, Casting, Higher Order Functions
Complexity: The Enemy
When building large programs, our enemy is complexity.
Some tools for managing complexity:
- Hierarchical abstraction.
- Create layers of abstraction, with clear abstraction barriers!
- “Design for change” (D. Parnas)
- Organize program around objects.
- Let objects decide how things are done.
- Hide information others don’t need.
As the user of an ArrayDeque
, you cannot observe its internals.
- Even when writing tests, you don’t (usually) want to peer inside.
Java is a great language for enforcing abstraction barriers with syntax.
A module is said to be encapsulated if its implementation is completely hidden, and it can be accessed only through a documented interface.
- Instance variables
private
. Methods like resizeprivate
. - As we’ll see: Implementation inheritance (e.g. extends) breaks encapsulation!
Suppose we have a Dog
class with the two methods shown.
1 | public void bark() { |
We could just as easily have implemented methods as shown below.
- From the outside, functionality is exactly the same, it’s just a question of aesthetics.
1 | public void bark() { |
Higher Order Functions
Higher Order Function: A function that treats another function as data.
Example in Python:
1 | def tenX(x): |
Old School (Java 7 and earlier)
- Fundamental issue: Memory boxes (variables) cannot contain pointers to functions.
Can use an interface instead: Java code below is equivalent to given python code.
1 | public interface IntUnaryFunction { |
In Java 8, new types were introduced: now can hold references to methods.
- You’re welcome to use these features, but we won’t teach them.
- Why? The old way is still widely used, e.g. Comparators (see next lecture).
1 | public class Java8HoFDemo { |
Implementation Inheritance Cheatsheet
VengefulSLList
extends SLList
means a VenglefulSLList
is-an SLList
. Inherits all members!
- Variables, methods, nested classes.
- Not constructors.
- Subclass constructor must invoke superclass constructor first.
- Use super to invoke overridden superclass methods and constructors.
Invocation of overridden methods follows two simple rules:
- Compiler plays it safe and only lets us do things allowed by
static
type. - Compiler chooses 2
- For overridden methods the actual method invoked is based on dynamic type of invoking expression, e.g. Dog.maxDog(d1, d2).bark(); Does not apply to overloaded methods!
- Can use casting to overrule compiler type checking.