One of the manifestations of these ideas is Object Oriented Program. Create compound structures consisting of multiple members.
Data members referred to as fields.
Function members referred to as methods.
Classes form the blueprint for
data and functions.
Objects are concrete realizations of a class.
class Spot {
float x, y, radius;
void display() {
ellipse(x, y, radius, radius);
}
Spot(){
x = 50.0;
y = 50.0;
radius = 30.0;
}
Spot(float x, float y, float r) {
this.x = x;
this.y = y;
this.radius = r;
}
}
Spot sp1, sp2;
void setup(){
sp1 = new Spot();
sp2 = new Spot(75, 80, 15);
}
void draw(){
sp1.display();
sp2.display();
}
This is definitely a matter of taste, style, and experience.
General rule: if there are multiple data that should be operated on together, bundle into a class.
Complexity of subtyping relations (which we will briefly discuss today).
Industry as a whole has been swinging towards functional programming in the last 10 years, but many things are simply not possible (or very difficult) in a functional setting.
Yes. In fact, I highly encourage you to do so, although creating truly reusable classes is hard and so you'll probably have a little trouble at first.
Processing treats a .pde file with the same name as the folder as the "primary" PDE file. All other .pde files within the directory are assumed to be for classes.
The ability to design reusable code comes through trying to reuse nonresuable code!
class A {
float x, y;
A(float x){
this(x, 1.0);
}
A(float x, float y){
this.x = x;
this.y = y;
}
}
void setup(){
A a1 = new A(1.0);
A a2 = new A(2.0, 2.0);
}
Java will select the version to use based off of number and type of arguments.
Also works for regular functions and methods!
In this sense, a constructor is like a special method that returns a new instance of the class (i.e. a new object).
Any other famous Minecraft bugs?
What alternative to creating sparks are there?
A technique commonly called "object pooling". Instead of creating and deleting a bunch of objects, keep a pool of them on hand but don't display them.
Do we need to worry about memory allocation in Processing?
How many classes can be used within each other before program speed starts to suffer?
How many classes can be used within each other before program speed starts to suffer?
Languages like Python simply weren't used in the 90s because they were too slow!
Combinatorial explosions (e.g. \( 2^n \) runtimes) can bring even the fastest computer to its knees, but unless you're working with giant data (\(N \geq 10^{10} \)), minor overheads simply aren't going to matter.
The ability to bundle related data and functions together is nice, but can be obtained with other tools as well. In Python, we could use dicts, sets, and modules to bundle code/variables together.
Suppose we are trying to design a Bike
class. What pieces might we need for this class?
To animate:
Additional rule: wheels on front and back must be the same model.
class Bicycle{
Frame frame;
Wheel frontW;
Wheel backW;
float x, y;
float wheelDist;
Bicycle(Frame f, Wheel w){
// Initialize bike
}
void displayBike(){
// ?
}
void moveBike(float dx){
// ?
}
}
void displayBike() {
frame.drawAt(x, y);
frontW.drawAt(x+wheelDist/2, y);
backW.drawAt(x-wheelDist/2, y);
}
void moveBike(float dx) {
this.x += dx;
// Why can we compute one rotation for both?
float wheelRotation = dx / (Math.PI * frontW.diameter);
frontW.rotate(wheelRotation);
backW.rotate(wheelRotation);
}
Note: we don't have to do 100% of the work ourselves! Delegate work to components.
Allow us to break complex problems into simpler ones.
Don't need to know how to draw the entire bike: just have to know where to draw the wheels and let the wheels draw themselves!
We can ignore how certain things are implemented.
How is Wheel::rotate()
implemented? Don't know. Don't care!
Suppose we are trying to model multiple forms of transport vehicles. What classes do we have?
Has-a isn't really appropriate to describe the relationship between these!
Vehicle
Motorized Vehicle
Human-Powered Vehicle
Scooter
Car
Bus
Bicycle
Skateboard
A car does not contain a motorized vehicle, it is a motorized vehicle. It can do everything a motorized vehicle can and more.
Motorized Vehicle
Car
Bus
class MotorizedVehicle {
float fuel, speed;
void addFuel(float amount){ /* */ }
void accelerate(float rate){ /* */ }
}
class Car extends MotorizedVehicle {
color color;
}
class Bus extends MotorizedVehicle {
int numSeats;
}
Car myCar = new Car();
myCar.color = color(10, 20, 30);
myCar.addFuel(10.0);
myCar.accelerate(20.0);
extends
keyword to declare that a class is a subclass of another.Hmmmm.....
class MotorizedVehicle {
float fuel, speed;
void addFuel(float amount){ /* */ }
void accelerate(float rate){ /* */ }
MotorizedVehicle(float fuel){
if (fuel < 0){
// ERROR: Fuel cannot be negative!
this.fuel = 0.0;
} else {
this.fuel = fuel;
}
this.speed = 0.0;
}
}
When writing a constructor, construct the parent class by calling super().
class Car extends MotorizedVehicle {
color color;
Car(color c, float fuel){
super(fuel);
this.color = c;
}
}
class MotorizedVehicle {
float fuel, speed;
void addFuel(float amount){ /* */ }
void accelerate(float rate){ /* */ }
}
class Car extends MotorizedVehicle {
color color;
}
class Bus extends MotorizedVehicle {
int numSeats;
}
Suppose we have a MotorVehicle object. What can we do with it?
void doAThing(MotorVehicle v){
// What can we do to v?
}
What if v
is a Car
or a Bus
?
Car
is a MotorizedVehicle
, anywhere that we expect a MotorizedVehicle
, we can use a Car
instead!void doAThing(MotorVehicle v){
// Check fuel
if (fuel == 0){
v.addFuel(10);
}
v.accelerate(5);
}
MotorVehicle v1 = new MotorVehicle();
Car c1 = new Car();
Bus b1 = new Bus();
doAThing(v1);
doAThing(c1);
doAThing(b1);
MotorVehicle v1 = new Car(); // Tricky
Note that the opposite is not true!
void doThing2(Car c){ /* ... */ }
MotorVehicle v1 = new MotorVehicle();
doThing2(v1); // ERROR
class Foo {
...
void printHello() {
print("Hi I'm Foo");
}
}
class Bar extends Foo {
...
void printHello() {
print("Hi I'm Bar");
}
}
Foo f = new Foo();
Bar b = new Bar();
f.printHello();
b.printHello();
The method in the child class overrides the one in the parent!
class MotorizedVehicle {
float fuel, speed;
void addFuel(float amount){
fuel += amount;
}
void accelerate(float rate){
this.speed += rate;
this.fuel -= 0.01 * rate;
}
}
Motor Vehicles consume fuel to accelerate.
class Bus extends MotorizedVehicle {
int seats;
void accelerate(float rate){
this.speed += rate;
this.fuel -= seats * 0.01 * rate;
}
}
Buses need to consume more fuel the more seats they have.
void goGoGo(MotorVehicle v){
v.accelerate(100);
}
Do we need to worry about acceleration being incorrect (i.e. we need to do something to v to make it "work"?)
People sometimes get confused about the difference between is-a and has-a and model their problem with OOP incorrectly. This leads to what has sometimes been called "certifiably insane" designs.
Car inherits from ParkingGarage because parking garages contain cars
Person should multiple-inherit* from Head, Body, Arm, and Leg
* Multiple Inheritance is a feature that does not exist in Java or Processing
CarWithBumperSticker is a subclass of Car
A circle inherits from a point because I need to show off inheritance for this textbook
You may want to pull out your laptops and follow along, since some of this will be on the hands-on.
Spot
subclass ColorSpot
working in your code.Spot
subclass called TwoSpots
. (Dropdown > New Tab). TwoSpots
displays two ellipses around a center point.TwoSpots
object to a specific location. Do this without modifying the TwoSpots
class directly.