epubjs
Version:
Render ePub documents in the browser, across many devices
435 lines (271 loc) • 20.1 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta charset="utf-8"/>
<title>Getting Started with Processing</title>
<script type="text/javascript">
if(!window.atlasplugins) window.atlasplugins = {}
atlasplugins.codeMirrorSettings = {
theme: "3024-day"
}
</script>
<link href="http://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700" rel="stylesheet" type="text/css"> </link>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"> </script>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"> </script>
<link rel="stylesheet" type="text/css" href="theme/html/html.css"/>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/4.4.0/codemirror.min.css"/>
<link rel="stylesheet" type="text/css" href="https://d2uogd9jz9k9zm.cloudfront.net/processingjs-0.0.3.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js" type="text/javascript"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/4.4.0/codemirror.min.js" type="text/javascript"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/4.5.0/mode/clike/clike.min.js" type="text/javascript"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js" type="text/javascript"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/processing.js/1.4.8/processing.min.js" type="text/javascript"> </script>
<script src="https://d2uogd9jz9k9zm.cloudfront.net/processingjs-0.0.3.min.js" type="text/javascript"> </script>
<script type="text/javascript">
$(function() {
// Make all non runnable examples readonly codemirrors
$('pre:not(*[data-executable], .CodeMirror pre)').each(function(i, el) {
var textArea = $('<textarea>' + el.innerHTML + '</textarea>')
$(el).replaceWith(textArea);
var editor = CodeMirror.fromTextArea(textArea[0], {
mode: "text/x-java",
theme: "3024-day",
readOnly: true,
viewportMargin: 0
});
});
});
</script>
<style type="text/css">
/* This needs to come last to set auto height, and html.css is always included first */
.CodeMirror {
height: auto;
font-size: 14px;
padding: 15px;
border-radius: 5px;
}
.CodeMirror-scroll {
overflow-y: hidden;
overflow-x: auto;
height: auto;
}
</style>
<script type="text/javascript" src="theme/html/epub.js"> </script>
<script type="text/javascript" src="theme/html/reader.js"> </script>
</head>
<body data-type="book" id="viewer">
<section data-type="chapter" data-pdf-bookmark="Chapter 9. Objects" id="objects">
<h1>Objects</h1>
<p><em>Object-oriented programming</em> (OOP) is a different way to think about your programs. Although the term “object-oriented programming” may sound intimidating, there’s good news: you’ve been working with objects since <a data-type="xref" href="ch06.html#media">Chapter 6</a>, when you started using <em>PImage</em>, <em>PFont</em>, <em>String</em>, and <em>PShape</em>. Unlike the primitive data types <em>boolean</em>, <em>int</em>, and <em>float</em>, which can store only one value, an object can store many. But that’s only a part of the story. Objects are also a way to group variables with related functions. Because you already know how to work with variables and functions, objects simply combine what you’ve already learned into a more understandable package.</p>
<p>Objects are important, because they break up ideas into smaller building blocks. This mirrors the natural world where, for instance, organs are made of tissue, tissue is made of cells, and so on. Similarly, as your code becomes more complicated, you must think in terms of smaller structures that form more complicated ones. It’s easier to write and maintain smaller, understandable pieces of code that work together than it is to write one large piece of code that does everything at once.</p>
<p>A software object is a collection of related variables and functions. In the context of objects, a variable is called a <em>field</em> (or <em>instance variable</em>) and a function is called a <em>method</em>. Fields and methods work just like the variables and functions covered in earlier chapters, but we’ll use the new terms to emphasize that they are a part of an object. To say it another way, an object combines related data (fields) with related actions and behaviors (methods). The idea is to group together related data with related methods that act on that data.</p>
<p>For instance, to model a radio, think about what parameters can be adjusted and the actions that can affect those parameters:</p>
<p>Fields: <em>volume</em>,
<em>frequency</em>, <em>band</em>(FM, AM),
<em>power</em>(on, off)<br/>
Methods: <em>setVolume</em>,
<em>setFrequency</em>, <em>setBand</em></p>
<p>Modeling a simple mechanical device is easy compared to modeling an organism like an ant or a person. It’s not possible to reduce such complex organisms to a few fields and methods, but it is possible to model enough to create an interesting simulation. The <em>Sims</em> video game is a clear example. This game is played by managing the daily activities of simulated people. The characters have enough personality to make a playable, addictive game, but no more. In fact, they have only five personality attributes: neat, outgoing, active, playful, and nice. With the knowledge that it’s possible to make a highly simplified model of complex organisms, we could start programming an ant with only a few fields and methods:</p>
<p>Fields: <em>type</em>(worker, soldier),
<em>weight</em>, <em>length</em><br/>
Methods: <em>walk</em>, <em>pinch</em>,
<em>releasePheromones</em>,
<em>eat</em></p>
<p>If you made a list of an ant’s fields and methods, you might choose to focus on different aspects of the ant to model. There’s no right way to make a model, as long as you make it appropriate for the purpose of your program’s goals.</p>
<section data-type="sect1" data-pdf-bookmark="Classes and Objects" id="classes_and_objects">
<h1>Classes and Objects</h1>
<p>Before you can create an object, you must define a class. A <em>class</em> is the specification for an object. Using an architectural analogy, a class is like a blueprint for a house, and the object is like the house itself. Each house made from the blueprint can have variations, and the blueprint is only the specification, not a built structure. For example, one house can be blue and the other red; one house might come with a fireplace and the other without. Likewise with objects, the class defines the data types and behaviors, but each object (house) made from a single class (blueprint) has variables (color, fireplace) that are set to different values. To use a more technical term, each object is an <em>instance</em> of a class and each instance has its own set of fields and methods.</p>
<section data-type="sect2" data-pdf-bookmark="Define a Class" id="define_a_class">
<h2>Define a Class</h2>
<p>Before you write a class, we recommend a little planning. Think about what fields and methods your class should have. Do a little brainstorming to imagine all the possible options and then prioritize and make your best guess about what will work. You’ll make changes during the programming process, but it’s important to have a good start.</p>
<p>For your fields, select clear names and decide the data type for each. The fields inside a class can be any type of data. A class can simultaneously hold many booleans, floats, images, strings, and so on. Keep in mind that one reason to make a class is to group together related data elements. For your methods, select clear names and decide the return values (if any). The methods are used to change the values of the fields and to perform actions based on the fields’ values.</p>
<p>For our first class, we’ll convert <a data-type="xref" href="ch07.html#example_7-9_colon_move_shapes_randomly">“<a href="http://examples.oreilly.com/0636920000570/interactive_examples/index.php?example=Ex_07_09">Example 7-9: Move Shapes Randomly</a>”</a> from earlier in the book. We start by making a list of the fields from the example:</p>
<pre data-type="programlisting">float x
float y
int diameter
float speed</pre>
<p>The next step is to figure out what methods might be useful for the class. In looking at the <em>draw()</em> function from the example we’re adapting, we see two primary components. The position of the shape is updated and drawn to the screen. Let’s create two methods for our class, one for each task:</p>
<pre data-type="programlisting">void move()
void display()</pre>
<p>Neither of these methods return a value, so they both have the return type <em>void</em>. When we next write the class based on the lists of fields and methods, we’ll follow four steps:</p>
<ol>
<li>
<p>Create the block.</p>
</li>
<li>
<p>Add the fields.</p>
</li>
<li>
<p>Write a <em>constructor</em> (explained shortly) to assign values to the fields.</p>
</li>
<li>
<p>Add the methods.</p>
</li>
</ol>
<p>First, we create a block:</p>
<pre data-type="programlisting">class JitterBug {
}</pre>
<p>Notice that the keyword <em>class</em> is lowercase and the name <em>JitterBug</em> is uppercase. Naming the class with an uppercase letter isn’t required, but it is a convention (that we strongly encourage) used to denote that it’s a class. (The keyword <em>class</em>, however, must be lowercase because it’s a rule of the programming language.)</p>
<p>Second, we add the fields. When we do this, we have to decide which fields will have their values assigned through a <em>constructor</em>, a special method used for that purpose. As a rule of thumb, field values that you want to be different for each class are passed in through the constructor, and the other field values can be defined when they are declared. For the <em>JitterBug</em> class, we’ve decided that the values for <em>x</em>, <em>y</em>, and <em>diameter</em> will be passed in. So the fields are declared as follows:</p>
<pre data-type="programlisting">class JitterBug {
float x;
float y;
int diameter;
float speed = 0.5;
}</pre>
<p>Third, we add the constructor. The constructor always has the same name as the class. The purpose of the constructor is to assign the initial values to the fields when an object (an instance of the class) is created (<a data-type="xref" href="#passing_values_into_the_constructor">Figure 9-1</a>). The code inside the constructor block is run once when the object is first created. As discussed earlier, we’re passing in three parameters to the constructor when the object is initialized. Each of the values passed in is assigned to a temporary variable that exists only while the code inside the constructor is run. To clarify this, we’ve added the name <em>temp</em> to each of these variables, but they can be named with any terms that you prefer. They are used only to assign the values to the fields that are a part of the class. Also note that the constructor never returns a value and therefore doesn’t have <em>void</em> or another data type before it. After adding the constructor, the class looks like this:</p>
<pre data-type="programlisting">class JitterBug {
float x;
float y;
int diameter;
float speed = 0.5;
JitterBug(float tempX, float tempY, int tempDiameter) {
x = tempX;
y = tempY;
diameter = tempDiameter;
}
}</pre>
<p>The last step is to add the methods. This part is straightforward; it’s just like writing functions, but here they are contained within the class. Also, note the code spacing. Every line within the class is indented a few spaces to show that it’s inside the block. Within the constructor and the methods, the code is spaced again to clearly show the hierarchy:</p>
<pre data-type="programlisting">class JitterBug {
float x;
float y;
int diameter;
float speed = 2.5;
JitterBug(float tempX, float tempY, int tempDiameter) {
x = tempX;
y = tempY;
diameter = tempDiameter;
}
void move() {
x += random(-speed, speed);
y += random(-speed, speed);
}
void display() {
ellipse(x, y, diameter, diameter);
}
}</pre>
<figure id="passing_values_into_the_constructor">
<img src="images/Fig_09_01.png" alt="Fig 09 01"/>
<figcaption>Passing values into the constructor.</figcaption>
</figure>
</section>
<section data-type="sect2" data-pdf-bookmark="Example 9-1: Make an Object" id="example_9-1_colon_make_an_object">
<h2><a href="http://examples.oreilly.com/0636920000570/interactive_examples/index.php?example=Ex_09_01">Example 9-1: Make an Object</a></h2>
<p>Now that you have defined a class, to use it in a program you must define an object from that class. There are two steps to create an object:</p>
<ol>
<li>
<p>Declare the object variable.</p>
</li>
<li>
<p>Create (initialize) the object with the keyword <em>new</em>.</p>
</li>
</ol>
<p>We’ll start by showing how this works within a Processing sketch and then continue by explaining each part in depth:</p>
<figure>
<img src="images/Ex_09_01.png" alt="Ex 09 01"/>
<figcaption/>
</figure>
<pre data-type="programlisting">JitterBug bug; // Declare object
void setup() {
size(480, 120);
smooth();
// Create object and pass in parameters
bug = new JitterBug(width/2, height/2, 20);
}
void draw() {
bug.move();
bug.display();
}
// Put a copy of the JitterBug class here</pre>
<p>Each class is a <em>data type</em> and each object is a <em>variable</em>. We declare object variables in a similar way to variables from primitive data types like <em>boolean</em>, <em>int</em>, and <em>float</em>. The object is declared by stating the data type followed by a name for the variable:</p>
<pre data-type="programlisting">JitterBug bug;</pre>
<p>The second step is to initialize the object with the keyword <em>new</em>. It makes space for the object in memory and creates the fields. The name of the constructor is written to the right of the <em>new</em> keyword, followed by the parameters into the constructor, if any:</p>
<pre data-type="programlisting">JitterBug bug = new JitterBug(200.0, 250.0, 30);</pre>
<p>The three numbers within the parentheses are the parameters that are passed into the <em>JitterBug</em> class constructor. The number of these parameters and their data types must match those of the constructor.</p>
</section>
<section data-type="sect2" data-pdf-bookmark="Example 9-2: Making Multiple Objects" id="example_9-2_colon_making_multiple_object">
<h2><a href="http://examples.oreilly.com/0636920000570/interactive_examples/index.php?example=Ex_09_02">Example 9-2: Making Multiple Objects</a></h2>
<p>In <a data-type="xref" href="#example_9-1_colon_make_an_object">“<a href="http://examples.oreilly.com/0636920000570/interactive_examples/index.php?example=Ex_09_01">Example 9-1: Make an Object</a>”</a>, we see something else new: the period (dot) that’s used to access the object’s methods inside of <em>draw()</em>. The dot operator is used to join the name of the object with its fields and methods. This becomes clearer in this example, where two objects are made from the same class. The <em>jit.move()</em> command refers to the <em>move()</em> method that belongs to the object named <em>jit</em>, and <em>bug.move()</em> refers to the <em>move()</em> method that belongs to the object named <em>bug</em>:</p>
<figure>
<img src="images/Ex_09_02.png" alt="Ex 09 02"/>
<figcaption/>
</figure>
<pre data-type="programlisting">JitterBug jit;
JitterBug bug;
void setup() {
size(480, 120);
smooth();
jit = new JitterBug(width * 0.33, height/2, 50);
bug = new JitterBug(width * 0.66, height/2, 10);
}
void draw() {
jit.move();
jit.display();
bug.move();
bug.display();
}
// Put a copy of the JitterBug class here</pre>
<p>Now that the class exists as its own module of code, any changes will modify the objects made from it. For instance, you could add a field to the <em>JitterBug</em> class that controls the color, or another that determines its size. These values can be passed in using the constructor or assigned using additional methods, such as <em>setColor()</em> or <em>setSize()</em>. And because it’s a self-contained unit, you can also use the <em>JitterBug</em> class in another sketch.</p>
<p>Now is a good time to learn about the tab feature of the Processing Environment (<a data-type="xref" href="#code_can_be_split_into_different_tabs_to">Figure 9-2</a>). Tabs allow you to spread your code across more than one file. This makes longer code easier to edit and more manageable in general. A new tab is usually created for each class, which reinforces the modularity of working with classes and makes the code easy to find.</p>
<p>To create a new tab, click on the arrow at the righthand side of the tab bar. When you select New Tab from the menu, you will be prompted to name the tab within the message window. Using this technique, modify this example’s code to try to make a new tab for the <em>JitterBug</em> class.</p>
<div data-type="note">
<p>Each tab shows up as a separate <em>.pde</em> file within the sketch’s folder.</p>
</div>
<figure id="code_can_be_split_into_different_tabs_to">
<img src="images/Fig_09_02.png" alt="Fig 09 02"/>
<figcaption>Code can be split into different tabs to make it easier to manage.</figcaption>
</figure>
</section>
</section>
<section data-type="sect1" data-pdf-bookmark="Robot 7: Objects" id="robot_7_colon_objects">
<h1><a href="http://examples.oreilly.com/0636920000570/interactive_examples/index.php?example=Robot7_Objects">Robot 7: Objects</a></h1>
<figure>
<img src="images/NRobot_Objects.png" alt="NRobot Objects"/>
<figcaption/>
</figure>
<p>A software object combines methods (functions) and fields (variables) into one unit. The <em>Robot</em> class in this example defines all of the robot objects that will be created from it. Each <em>Robot</em> object has its own set of fields to store a position and the illustration that will draw to the screen. Each has methods to update the position and display the illustration.</p>
<p>The parameters for <em>bot1</em> and <em>bot2</em> in <em>setup()</em> define the x- and y-coordinates and the <em>.svg</em> file that will be used to depict the robot. The <em>tempX</em> and <em>tempY</em> parameters are passed into the constructor and assigned to the <em>xpos</em> and <em>ypos</em> fields. The <em>svgName</em> parameter is used to load the related illustration. The objects (<em>bot1</em> and <em>bot2</em>) draw at their own location and with a different illustration because they each have unique values passed into the objects through their constructors:</p>
<pre data-type="programlisting">Robot bot1;
Robot bot2;
void setup() {
size(720, 480);
bot1 = new Robot("robot1.svg", 90, 80);
bot2 = new Robot("robot2.svg", 440, 30);
smooth();
}
void draw() {
background(204);
// Update and display first robot
bot1.update();
bot1.display();
// Update and display second robot
bot2.update();
bot2.display();
}
class Robot {
float xpos;
float ypos;
float angle;
PShape botShape;
float yoffset = 0.0;
// Set initial values in constructor
Robot(String svgName, float tempX, float tempY) {
botShape = loadShape(svgName);
xpos = tempX;
ypos = tempY;
angle = random(0, TWO_PI);
}
// Update the fields
void update() {
angle += 0.05;
yoffset = sin(angle) * 20;
}
// Draw the robot to the screen
void display() {
shape(botShape, xpos, ypos + yoffset);
}
}</pre>
</section>
</section>
</body>
</html>