Generics, Proxy, and The Compile Timex

Download Report

Transcript Generics, Proxy, and The Compile Timex

Generics, Proxy, and The Compile
Time Type Checking Debate
You are either with us or against us.
Please snarf the code for today’s class
Two Camps
C++
• Strong Type Checking
• Ensured at compile time
that you never called a
method on an object that
didn’t support it
• Focused on efficient
compilation
• *Very* complex type
system, including
“templates”
Smalltalk
• Variables do not have
types
• Extremely easy to call a
method on an object that
didn’t support it
• Not super efficient (but
not terrible)
• Pretty simple type system
(at least on the
surface)…also quite
flexible
Why Does Type Checking Inhibit
Flexibility?
• Example: The Proxy pattern
• Scenario:
You’ve written a very cool application that visualizes large data sets
(represented as objects that implement the DataSource interface). Your
visualizer takes a list of DataSource objects, and lets you choose the data
to visualize.
Bad news: some of these data sets are really huge. So to create the
DataSource objects really slows down your system, which is bad because
most of the DataSources won’t actually get used. What you want is to
only load the data if it’s really necessary (when the getData is called).
But you’d like to do this without adding complexity to the Visualizer
object OR to the GiganticDataSource object that actually loads the data.
Hint: It’s sort of like a Decorator
Solution: A Proxy
•
•
•
Make a new class GiganticDataSourceProxy that has a filename and has an
instance variable of type GiganticDataSource
Initially, the variable is null
But then, when somebody calls getData on the proxy, the proxy actually creates a
GiganticDataSource and loads the data, then forwards the results
GiganticDataSourceProxy data = new
GiganticDataSourceProxy(“myData.dat”);
//does not really load the file
//..a lot of other code…
//Now the proxy creates a new GiganticDataSource and passes the
// get data call to it
data.getData(77);
//subsequent calls are just forwarded to the proxy’s internal
// GiganticDataSource object
data.getData(12);
Proxy Objects Exist in Both Strongly
Typed Object Oriented Languages and
Weekly Typed Ones
• Used to delay initialization or other expensive
operations
• Used to hide “remote” objects that are actually
running on distant computers
• Sometimes even protect certain functions from
being run (although I tend to think this particular
use blurs the line between proxy objects and
decorators)
Can We Build a Generic Proxy Object?
•
•
•
That is, initially does nothing but then creates the object when a method is called
on it
In C++ or Java…no because that “generic” proxy would not implement the
appropriate interface
In a language with untyped variables like Smalltalk, Ruby or Python…yes. They
usually even have a special method that you can override when someone calls a
method you wouldn’t normally support
public exampleMethodWithNoTypes(myVar) {
myVar.doFunction(); //myVar could be any type
//if it is not a supported function, an
//exception would be thrown
return myVar.doOtherThing();
}
Generics
• Deal with some of the problems of Strong Typed Languages
• Prior to Java 1.5, all collections in Java used to take and return
objects
public void someFunction(ArrayList list) {
SpecificClass var = (SpecificClass) list.get(0);
var.callSpecificMethod();
}
• Combines the verbosity of Java with the poor type checking of
Smalltalk
• So generics were added so you can say ArrayList<String> (or
whatever)
Imagine We Decided to Make a
SpecificSpriteGroup
SpecificSpriteGroup<NinjaSprite> n = new
SpecificSpriteGroup<NinjaSprite>();
• Don’t make it inherit from SpriteGroup at least
not yet…make it have an array list of sprites
and a method addSprite that adds a sprite of
the appropriate type
A Few Complications
• getActive…goes through the list of sprites and
determines which one is active
• AddAll…we would like to be able to add a list
of Sprites
Write
• removeInactiveSprites
• (if you have time) sort…which should take a
comparator