[ Team LiB ] |
Lab 19.2 Exercises19.2.1 Use Nested RecordsIn this exercise, you will learn more about nested records. Create the following PL/SQL script:
Answer the following questions:
|
[ Team LiB ] |
[ Team LiB ] |
Lab 19.2 Exercises19.2.1 Use Nested RecordsIn this exercise, you will learn more about nested records. Create the following PL/SQL script:
Answer the following questions:
|
[ Team LiB ] |
|
Chapter 1. IntroductionIt's no secret that the Unix operating system has emerged as a standard operating system. For programmers who have been using Unix for many years now, this came as no surprise: The Unix system provides an elegant and efficient environment for program development. After all, this is what Dennis Ritchie and Ken Thompson strived for when they developed Unix at Bell Laboratories in the late 1960s. One of the strongest features of the Unix system is its wide collection of programs. More than 200 basic commands are distributed with the standard operating system. These commands (also known as tools) do everything from counting the number of lines in a file, to sending electronic mail, to displaying a calendar for any desired year. But the real strength of the Unix system comes not entirely from this large collection of commands but also from the elegance and ease with which these commands can be combined to perform far more sophisticated functions. To further this end, and also to provide a consistent buffer between the user and the guts of the Unix system (the kernel), the shell was developed. The shell is simply a program that reads in the commands you type and converts them into a form more readily understood by the Unix system. It also includes some fundamental programming constructs that let you make decisions, loop, and store values in variables. The standard shell distributed with Unix and Linux systems derives from AT&T's distribution, which evolved from a version originally written by Stephen Bourne at Bell Labs. Since then, the IEEE created standards based on the Bourne shell and the other more recent shells. The current version of this standard as of this revision is the Shell and Utilities volume of IEEE Std 1003.1-2001, also known as the POSIX standard. This shell is what we propose to teach you about in this book. The examples in this book were tested on both SunOS 5.7 running on a Sparcstation Ultra-30 and on Silicon Graphics IRIX 6.5 running on an Octane; some examples were also run on Red Hat Linux 7.1 and Cygwin. All examples, except some Bash examples in Chapter 15, were run using the Korn shell, although many were also run with Bash. Many Unix systems are still around that have Bourne shell derivatives and utilities not compliant with the POSIX standard. We'll try to note this throughout the text wherever possible; however, there are so many different versions of Unix from so many different vendors that it's simply not possible to mention every difference. If you do have an older Unix system that doesn't supply a POSIX-compliant shell, there's still hope. We'll list resources at the end of this book where you can obtain free copies of three different POSIX-compliant shells. Because the shell offers an interpreted programming language, programs can be written, modified, and debugged quickly and easily. We turn to the shell as our first choice of programming language. After you become adept at programming in the shell, you too may turn to it first. This book assumes that you are familiar with the fundamentals of the Unix system; that is, that you know how to log in; how to create files, edit them, and remove them; and how to work with directories. But in case you haven't used the Unix system for a while, we'll examine the basics in Chapter 2, "A Quick Review of the Basics." Besides the basic file commands, filename substitution, I/O redirection, and pipes are also reviewed in Chapter 2. Chapter 3, "What Is the Shell?," reveals what the shell really is. You'll learn about what happens every time you log in to the system, how the shell program gets started, how it parses the command line, and how it executes other programs for you. A key point made in Chapter 3 is that the shell is just a program; nothing more, nothing less. Chapter 4, "Tools of the Trade," provides tutorials on tools useful in writing shell programs. Covered in this chapter are cut, paste, sed, grep, sort, tr, and uniq. Admittedly, the selection is subjective, but it does set the stage for programs that we'll develop throughout the remainder of the book. Also in Chapter 4 is a detailed discussion of regular expressions, which are used by many Unix commands such as sed, grep, and ed. Chapters 5 through 10 teach you how to put the shell to work for writing programs. You'll learn how to write your own commands; use variables; write programs that accept arguments; make decisions; use the shell's for, while, and until looping commands; and use the read command to read data from the terminal or from a file. Chapter 6, "Can I Quote You on That?," is devoted entirely to a discussion on one of the most intriguing (and often confusing) aspects of the shell: the way it interprets quotes. By this point in the book, all the basic programming constructs in the shell will have been covered, and you will be able to write shell programs to solve your particular problems. Chapter 11, "Your Environment," covers a topic of great importance for a real understanding of the way the shell operates: the environment. You'll learn about local and exported variables; subshells; special shell variables such as HOME, PATH, and CDPATH; and how to set up your .profile file. Chapter 12, "More on Parameters," and Chapter 13, "Loose Ends," tie up some loose ends, and Chapter 14, "Rolo Revisited," presents a final version of a phone directory program called rolo that is developed throughout the book. Chapter 15, "Interactive and Nonstandard Shell Features," discusses features of the shell that either are not formally part of the IEEE POSIX standard shell (but are available in most Unix and Linux shells) or are mainly used interactively instead of in programs. Appendix A, "Shell Summary," summarizes the features of the IEEE POSIX standard shell. Appendix B, "For More Information," lists references and resources, including the Web sites where different shells can be downloaded. The philosophy this book uses is to teach by example. Properly chosen examples do a far superior job at illustrating how a particular feature is used than ten times as many words. The old "A picture is worth…" adage seems to apply just as well to examples. You are encouraged to type in each example and test it on your system, for only by doing can you become adept at shell programming. You also should not be afraid to experiment. Try changing commands in the program examples to see the effect, or add different options or features to make the programs more useful or robust. At the end of most chapters you will find exercises. These can be used as assignments in a classroom environment or by yourself to test your progress. This book teaches the IEEE POSIX standard shell. Incompatibilities with earlier Bourne shell versions are noted in the text, and these tend to be minor. Acknowledgments from the first edition of this book: We'd like to thank Tony Iannino and Dick Fritz for editing the manuscript. We'd also like to thank Juliann Colvin for performing her usual wonders copy editing this book. Finally, we'd like to thank Teri Zak, our acquisitions editor, and posthumously Maureen Connelly, our production editor. These two were not only the best at what they did, but they also made working with them a real pleasure. For the first revised edition of this book, we'd like to acknowledge the contributions made by Steven Levy and Ann Baker, and we'd like to also thank the following people from Sams: Phil Kennedy, Wendy Ford, and Scott Arant. For the second revised edition of this book, we'd like to thank Kathryn Purdum, our acquisitions editor, Charlotte Clapp, our project editor, and Geneil Breeze, our copy editor. |
|
Chapter 6. Exception HandlersIt is a sad fact of life that most programmers never take the time to properly bullet-proof their programs. Instead, wishful thinking often reigns. Most of us find it hard enoughand more than enough workto simply write the code that implements the positive aspects of an application: maintaining customers, generating invoices, and so on. It is devilishly difficult, from both a psychological standpoint and a resources perspective, to focus on the negative: for example, what happens when the user presses the wrong key? If the database is unavailable, what should I do? As a result, we write applications that assume the best of all possible worlds, hoping that our programs are bug-free, that users will enter the correct data in the correct fashion, and that all systems (hardware and software) will always be a "go." Of course, harsh reality dictates that no matter how hard you try, there will always be one more bug in your application. And your users will somehow always find just the right sequence of keystrokes to make a form implode. The challenge is clear: either you spend the time up-front to properly debug and bulletproof your programs, or you fight an unending series of rear-guard battles, taking frantic calls from your users and putting out the fires. You know what you should do. Fortunately, PL/SQL offers a powerful and flexible way to trap and handle errors |
Once the replication user is set up on both servers, you will
need to add some lines to the MySQL configuration file on the master and on the slave server. Depending on the type of
operating system, the configuration file will probably be
called either my.cnf or my.ini.
On Unix types of systems, the configuration file is usually located in the
/etc directory. On Windows systems, it's usually located in
c:\ or in c:\Windows. If the file doesn't exist on
your system, you can create it. Using a plain text editor (e.g., vi or
Notepad.exe)—one that won't add binary formatting—add
the following lines to the configuration file of the master under the
[mysqld] group heading:
[mysqld]
server-id = 1
log-bin = /var/log/mysql/bin.log
...
The server identification number is an arbitrary number used to
identify the master server in the binary log and in communications with
slave servers. Almost any whole number from 1 to 4294967295 is fine. Don't
use 0, as that causes problems. If you don't assign a server number, the
default server identification number of 1 will be used. The default is all
right for the master, but a different one should be assigned to each
slave. To keep log entries straight and avoid confusion in communications
between servers, it is very important that each slave have a unique
number.
In the configuration file excerpt shown here, the line containing
the log-bin option instructs MySQL to perform
binary logging to the path and file given. The actual path
and filename is mostly up to you. Just be sure that the directory exists
and that the user mysql is the owner, or at least has
permission to write to the directory. By default, if a path is not given,
the server's data directory is assumed as the path for log files. To leave
the defaults in place, give log-bin without the equals
sign and without the file pathname. This example shows the default
pathname. If you set the log file name to something else, keep the suffix
.log as shown here. It will be replaced automatically
with an index number (e.g., .000001) as new log files
are created when the server is restarted or the logs are flushed.
These two options are all that is required on the master. They can
be put in the configuration file or given from the command line when
starting the mysqld daemon each time. On the command
line, add the required double dashes before each option and omit the
spaces around the equals signs.
For InnoDB tables, you may want to add the following lines to the master's
configuration file:
innodb_flush_log_at_trx_commit = 1
sync-binlog = 1
These lines resolve problems that can occur with transactions and
binary logging.
For the slave server, we will need to add several options to the
slave's configuration file, reflecting the greater complexity and number
of threads on the slave. You will have to provide a server identification
number, information on connecting to the master server, and more log
options. Add lines similar to the following to the slave's configuration
file:
[mysqld]
server-id = 2
log-bin = /var/log/mysql/bin.log
log-bin-index = /var/log/mysql/log-bin.index
log-error = /var/log/mysql/error.log
relay-log = /var/log/mysql/relay.log
relay-log-info-file = /var/log/mysql/relay-log.info
relay-log-index = /var/log/mysql/relay-log.index
slave-load-tmpdir = /var/log/mysql/
skip-slave-start
...
At the top, you can see the server identification number is set to
2. The next stanzas set the logs and related index files. If these files
don't exist when the slave is started, it will automatically create
them.
The second stanza starts binary logging like on the master server,
but this time on the slave. This is the log that can be used to allow the
master and the slave to reverse roles as mentioned earlier. The binary log index file (log-bin.index)
records the name of the current binary log file to use. The
log-error option establishes an error log. Any problems
with replication will be recorded in this log.
The third stanza defines the relay log that records each entry in
the master server's binary log, along with related files mentioned
earlier. The relay-log-info-file option names the file
that records the most recent position in the master's binary log that the
slave recorded for later execution (not the most recent statement actually
executed by the slave), while the relay log index file in turn records the
name of the current relay log file to use for replication.
The slave-load-tmpdir option is necessary only if
you expect the LOAD DATA INFILE statement to
be executed on the server. This SQL statement is used to import data in
bulk into the databases. The slave-load-tmpdir option
specifies the temporary directory for those files. If you don't specify
the option, the value of the tmpdir variable will be
used. This relates to replication because the slave will log LOAD
DATA INFILE activities to the log files with the prefix
SQL_LOAD- in this directory. For security, you may not
want those logs to be placed in a directory such as
/tmp.
The last option, skip-slave-start, prevents the
slave from replicating until you are ready. The order and spacing of
options, incidentally, are a matter of personal style.
To set variables on the slave related to its connection with the
master (e.g., the master's host address), it is recommended that you use
the [click here] statement to set the values on the
slave. You could provide the values in the configuration file. However,
the slave will read the file only the first time you start up the slave
for replication. Because the values are stored in the master.info file, MySQL just relies
on that file during subsequent startups and ignores these options in the
main MySQL configuration file. The only time it adjusts the
master.info file contents is when you tell it to
explicitly through a [click here] statement. You could
edit the master.info file and
other replication information files directly, but you might cause more
problems in doing so. It's best to use the [click here]
statement to make changes. Here is an example:
CHANGE MASTER TO MASTER_HOST = 'master_host';
CHANGE MASTER TO MASTER_PORT = 3306;
CHANGE MASTER TO MASTER_USER = 'replicant';
CHANGE MASTER TO MASTER_PASSWORD = 'my_pwd';
This set of SQL statements provides information about the master
server. The first statement gives
the hostname (or the IP address) of the master. The next one provides the
port for the connection. Port 3306 is the default port for MySQL, but
another could be used for performance or security considerations. The next
two lines set the username and password for logging into the master
server. After you run these SQL statements, their values are stored in the
master.info file and you shouldn't need to rerun the
statements upon subsequent startups.
At this point, the servers should be configured properly. Next, you
will need to get the slave's data current by making a backup on the master
server and copying it manually to the slave. This is described in the
following section. If the master and slave are new servers and the master
has no data yet, you can skip the next section and proceed to Section 8.6."
6.3. System Tray IntegrationAnother common feature of instant messaging applications is integration into the system tray. Using this idea, we want Hyperbola to appear in the system tray as an icon representing the user's presence. This also allows Hyperbola to minimize to the system tray rather than continuing to be displayed in the task bar even though it is minimized. The tray items are also a popular location for adding actions related to your application. Figure 6-8 shows how this looks for Hyperbola. Figure 6-8. Context menu on the Hyperbola task tray itemTip If you are going to use the system tray, it is good practice to make its use optionalif every application put itself in the system tray, it would get cluttered. When it is enabled, it should be used to display important status information to the user and provide a quick access point for running frequent actions. Also, the system tray is not available on all platforms, so do not make it the focal point of your application's workflow. It should be used as an optional integration feature. In this section, we show you how to:
6.3.1. Obtaining a DisplayTo get the system tray, you need a Display. A Display is an SWT object that represents the underlying graphics system. Typically, the Display is not available until the window has been created. Figure 6-9 shows the WorkbenchWindow lifecycle and highlights the earliest point, in postWindowOpen(), where the Display is available. So, the first time a window is opened, the WorkbenchWindowAdvisor can get the Display via the window's shell and set up the system tray for Hyperbola. At this point, the tray item is created and configured such that when its menu is shown, the ActionBarAdvisor populates the menu. Figure 6-9. How the ActionBarAdvisor contributes actions to the task item6.3.2. Creating the Tray ItemThe code snippet below from ApplicationWorkbenchWindowAdvisor shows how the system tray item is created and how it operates. First, the item is created and configured and then listeners are added to support showing the menu and minimizing into the tray item. After the tray item is set up, a menu listener is added to it. That way, when the tray item is right-clicked, a context menu appears and is populated by the ActionBarAdvisor. Some platforms do not have system trays and initTaskItem() may return null. In that case, the tray item is not created. org.eclipsercp.hyperbola/ApplicationWorkbenchWindowAdvisor Note The image and tray item area are saved as fields on the WorkbenchWindowAdvisor so that they can be deleted when the window is closed. Since the ActionBarAdvisor already manages all of Hyperbola's actions, it is a good place to put the method that fills the system tray item's menu. This also allows the tray item menu to reuse actions created in the ActionBarAdvisor. Add the following snippet to ApplicationActionBarAdvisor: org.eclipsercp.hyperbola/ApplicationActionBarAdvisor A shell listener is added in the hookMinimize() method to the window so that the window is marked as hidden when minimized. This simulates minimizing the window into the task bar. When the window is invisible, the only indication that Hyperbola is running is the system tray icon. Another listener, also added in the hookMinimize() method, listens to the tray item to detect when it is selected. Selecting the task item is the cue that Hyperbola's window should be made visible if it had previously been minimized. After setting this up, run Hyperbola and look for the system tray icon. Right-click it and the context menu appears. Minimize Hyperbola and notice that Hyperbola is completely gone except for the task tray icon. Click the tray icon and Hyperbola reappears. |
|
The set CommandThe shell's set command is a dual-purpose command: it's used both to set various shell options as well as to reassign the positional parameters $1, $2, and so forth. The -x OptionThis option turns on trace mode in the shell. It does to the current shell what the command
did for the execution of the ctype program in Chapter 8, "Decisions, Decisions." From the point that the
command is executed, all subsequently executed commands will be printed to standard error by the shell, after filename, variable, and command substitution and I/O redirection have been performed. The traced commands are preceded by plus signs.
You can turn off trace mode at any time simply by executing set with the +x option:
You should note that the trace option is not passed down to subshells. But you can trace a subshell's execution either by running the shell with the -x option followed by the name of the program to be executed, as in
or you can insert a set -x command inside the file itself. In fact, you can insert any number of set -x and set +x commands inside your program to turn trace mode on and off as desired. set with No ArgumentsIf you don't give any arguments to set, you'll get an alphabetized list of all the variables that exist in your environment, be they local or exported:
Using set to Reassign Positional ParametersThere is no way to directly assign a value to a positional parameter; for example,
does not work. These parameters are initially set on execution of the shell program. The only way they may be changed is with the shift or the set commands. If words are given as arguments to set on the command line, those words will be assigned to the positional parameters $1, $2, and so forth. The previous values stored in the positional parameters will be lost forever. So
assigns a to $1, b to $2, and c to $3. $# also gets set to 3.
So after execution of the set, everything seems to work consistently: $#, $*, and the for loop without a list. set is often used in this fashion to "parse" data read from a file or the terminal. Here's a program called words that counts the number of words typed on a line (using the shell's definition of a "word"):
The program stores the line read in the shell variable line and then executes the command
This causes each word stored in line to be assigned to the positional parameters. The variable $# is also set to the number of words assigned, which is the number of words on the line. The -- OptionTry typing in a line to words that begins with a - and see what happens:
After the line was read and assigned to line, the command
was executed. After the shell did its substitution, the command line looked like this:
When set executed, it saw the - and thought that an option was being selected, thus explaining the error message. Another problem with words occurs if you give it a line consisting entirely of whitespace characters, or if the line is null:
To protect against both of these problems occurring, you can use the -- option to set. This tells set not to interpret any subsequent arguments on the command line as options. It also prevents set from displaying all your variables if no other arguments follow, as was the case when you typed a null line. So the set command in words should be changed to read
With the addition of a while loop and some integer arithmetic, the words program can be easily modified to count the total number of words on standard input, giving you your own version of wc -w:
After each line is read, the set command is executed to take advantage of the fact that $# will be assigned the number of words on the line. The -- option is supplied to set just in case any of the lines read begins with a - or consists entirely of whitespace characters. The value of $# is then added into the variable count, and the next line is read. When the loop is exited, the value of count is displayed. This represents the total number of words read.
(Our version is a lot slower than wc because the latter is written in C.) Here's a quick way to count the number of files in your directory:[1]
This is much faster than
because the first method uses only shell built-in commands. In general, your shell programs run much faster if you try to get as much done as you can using the shell's built-in commands. Other Options to setset accepts several other options, each of them enabled by preceding the option with a -, and disabled by preceding it with a +. The -x option that we have described here is perhaps the most commonly used. Others are summarized in Table A.9 in Appendix A. |
|
There are a couple of important requirements when supporting a web-based game from within the browser. The first is the Internet communication. Will your game require broadband-type speeds to function correctly, or will any Internet connection speeds suffice? Only you can answer this question. However, there is a factor that could narrow down the answer. The genre of game can dictate the types of communication required: strategy-based games would require much less bandwidth back and forth between client and server than an FPS game would. So, look at the type of game you plan to build, and think about the connection requirements you think you will need based on the amount of client/server communication necessary.
The more important Internet requirement is what the game's platform will be. This requirement boils down to two choices: one of an assortment of plug-ins, or JavaScript with Ajax.
There are few choices when it comes to plug-ins for browsers, and I am going to throw applets into this definition as well. Each type of plug-in has its advantages, of course, and the biggest disadvantage with all plug-ins is that they require a user to download software for them to work. The plug-ins that I will focus on are:
Flash
Shockwave
Java applets
Perhaps the most popular plug-in for browsers today is Flash. This could be because its interoperability within a browser has become nearly seamless. Whole sites are built using Flash to create all functionality and content. Media sites, especially those for movies, use Flash to allow more user interactivity.
Macromedia released Flash in 1996, after acquiring the technology from FutureWave Software. Adobe acquired Macromedia and its software in December 2005, and the current version of Flash is Flash CS3. Originally developed as a multimedia platform for the World Wide Web, Flash has grown and become a tool for user interaction, as well as a platform for games and complicated presentation that is much more difficult to produce using XHTML, CSS, and JavaScript. Flash uses the ActionScript programming language, which has the same syntax as JavaScript, as it is an implementation of ECMAScript. ActionScript allows a developer to interact with all of the objects created within Flash, as well as communicate with a server.
Flash is a small browser download, and according to Adobe's web site, it's available on nearly 99 percent of Internet-enabled desktops.[10] This makes it a good candidate for game development, and an alternative for web developers who have JavaScript experience. In fact, Ajax can be implemented within a Flash platform, as Flash uses ActionScript behind the scenes. ActionScript is a close cousin to JavaScript, and it follows ECMAScript more closely. Flash can be a good alternative for more complicated games in which you still wish to implement Ajax for communication between the client and the server.
[10] * Flash Player Statistics from Adobe Systems (http://www.adobe.com/products/player_census/flashplayer/)
Macromedia Director was introduced before Flash. It was followed shortly after by Shockwave, which Macromedia introduced around the same time as Flash, and although both are from the same company, Shockwave was a direct competitor to Flash. Shockwave was geared more toward game development from the start, having a more powerful graphics engine. This made it a larger plug-in, however, and its size kept it from enjoying the same widespread adoption as Flash. Shockwave's other limitation is that it is not compatible with all operating systems—in particular, Linux.
As noted earlier, Adobe bought Macromedia and all its products in 2005. The current version of Shockwave is 10.2.
Today's Shockwave is well suited to games, as it renders faster, includes hardware-accelerated 3D images, and offers blend modes for layered display of graphical assets. This allows it to build much more graphically rich games, something Flash cannot do. The trade-off is its lack of support for operating systems other than Windows and Mac OS X, its larger initial download size, and its slower startup time in browsers.
Java applets are specialized Java programs intended to run within browsers as plug-ins. The browser's operating system must have a compatible version of the Java Runtime Environment (JRE) for applets to function correctly. The most recent version of the JRE at the time of this writing is JRE 6 Update 2.
You create an applet by extending a new class for the program with the Applet class. Any other classes supported by the JRE on the client can be used in the applet. The advantage is that you can build a pretty robust gaming application to run in the browser. Just remember that the larger and more complex the application, the larger the size of the file that the browser must download.
Java applets can be well suited for games, as they have Java's graphing capabilities and the ability to handle network connections not available using Ajax. The only thing to remember is that the user must have the JRE associated with your build of the applet. This download may take a very long time, though, if the user doesn't have a compatible version of the JRE already installed. This may turn people away from using your gaming applet.
Ajax solutions to browser-based game programming have the advantage of complete browser reliance without the need for any additional software. This can improve startup times and give a completely seamless look within the browser. The real advantage over plug-ins for game programming is that there is nothing else new to learn.
An Ajax solution for game development must rely on XHTML, CSS, JavaScript, and XML/JavaScript Object Notation (JSON). Do these skills sound familiar? They ought to, as they are the skills that every developer should possess. What's more, they are the skills that you either knew before reading this book, or hopefully have gained by now. This can be appealing to a developer who has always wanted to program a game, but has lacked the skills to create one on a traditional platform (i.e., the desktop).
So that you can better understand the parts of a typical game, I will break them down in a modular manner, as each component of the game will need its own Ajax functionality. The parts that we will be interested in are:
Character animation
Collisions
Input
Putting all of this together will result in a rough game client that can communicate with a server and handle the basic functionality most games need.
8.5. Device Drivers and the GPLMuch discussion and debate surrounds the issue of device drivers and how the terms of the GNU Public License apply to device drivers. The first test is well understood: If your device driver (or any software, for that matter) is based, even in part, on existing GPL software, it is called a derived work. For example, if you start with a current Linux device driver and modify it to suit your needs, this is certainly considered a derived work, and you are obligated to license this modified device driver under the terms of the GPL, observing all its requirements. This is where the debate comes in. First, the disclaimer. This is not a legal opinion, and the author is not a lawyer. Some of these concepts have not been tested in court as of this writing. The prevailing opinion of the legal and open source communities is that if a work can be proven [8] to be independently derived, and a given device driver does not assume "intimate knowledge" of the Linux kernel, the developers are free to license it in any way they see fit. If modifications are made to the kernel to accommodate a special need of the driver, it is considered a derived work and, therefore, is subject to the GPL.
A large and growing body of information exists in the open source community regarding these issues. It seems likely that, at some point in the future, these concepts will be tested in a court of law and precedent will be established. How long that might take is anyone's guess. If you are interested in gaining a better understanding of the legal issues surrounding Linux and open source, you might enjoy www.open-bar.org. |
[ Team LiB ] |
22.1 Classes, objects and constructorsIn object-oriented programming (OOP) we use a special kind of data structure called a class. A class is quite similar to an ordinary C struct. Particular instances of some class type are called objects. As well as having members which are data fields, a class also has members that are functions. If SomeClass
The first line says that K is an object of the class type SomeClass. You can also say that 'K is a SomeClass The second line says to let the object K call the class member function SomeFunction Sometimes a class's constructor function takes arguments. MFC includes, for instance, a CPoint
It is allowable for a class to have several kinds of constructors. The constructors can be thought of as functions that you can use to create objects of the class type. We need to mention still another way of initializing an object. Suppose that you want to have, say, a global SomeClass
When you declare a pointer to a class like this, no initialization happens. No constructor gets called. Depending on the context, a junk value like CDCDCDCD0x The way that you make *sc_ptr correspond to a legitimate object is that later, down in the code when you find out what parameters, say x and y, you want to give to the SomeClass
In C++, new When you create an object of a given class type the constructor gets called; the constructor encapsulates the initialization and the allocation code. You can 'create' an object either by declaring it as a variable or by using the new Note that in Java, all class instance variables are of the pointer type. Java doesn't explicitly use the * Saying the same thing again in a different way:
Sometimes beginning Java programmers have the impression that 'Java has no pointers.' But exactly the opposite is true. Everything in Java is a pointer, other than primitives like int |
[ Team LiB ] |
| |||||||||||||||
Recipe 21.15. Creating a GUI Application with Ruby/GTKProblemYou want to write a GUI application that uses the SolutionUse the Ruby bindings to Gnome's
Figure 21-5. You are a GTK troutDiscussionGnome is one of the two most popular Unix desktop suites. The Ruby-Gnome2 project provides and documents Ruby bindings to Gnome's vast array of C libraries. You can write Ruby applications that fully integrate with the Gnome desktop, but in this recipe I'm going to focus on the basics of the Gnome GUI library GTK. Although the details are different, the sample program above is basically the same as it would be with Tk (Recipe 21.12) or the wxRuby library (Recipe 21.13). You create two widgets (a window and a label), attach the label to the window, and tell the GUI library to display the window. As with Tk and wxRuby, the application goes into a display loop, capturing user events like mouse clicks. The sample program won't actually respond to any user events, though, so let's create a Ruby/GTK version of the stopwatch program seen in previous GUI recipes. The core methods, the ones that actually implement the stopwatch, are basically the same as the corresponding methods in the Tk and wxRuby recipes. Since GTK doesn't have a timer widget, I've implemented a simple timer as a separate thread. The other point of interest is the HTML-like markup that GTK uses to customize the font size and weight of the stopwatch text.
Now begins the GUI setup. Ruby uses VBox and HBox objects to pack widgets into the display area. The stopwatch application will give its main window a single VBox containing three widgets arranged from top to bottom: a menu bar, a label (displaying the stopwatch time), and a button (to start and stop the stopwatch):
The program's menu bar consists of many nested MenuBar, Menu, and MenuItem objects. Rather than create these objects ourselves, we define the parameters of our menu bar in a nested array, and pass it into an ItemFactory object:
The label and the button are pretty simple: just define them and pack them into the VBox:
I've been calling a nonexistent method Stopwatch#set_button_handler whenever I want to modify the code that runs when the user clicks the button. I close out the Stopwatch class by defining that method (Figure 21-6):
In the Tk recipe, I simply called a button's command method whenever I needed to change the code block that runs when the user clicks the button. So why this set_ button_handler code? Why not just call signal_connect whenever I need to change what the button does here? I can't do that because GTK lets you associate multiple code blocks with a single event. This doesn't usually come up, but it's a problem here because I'm changing the function of a button. Figure 21-6. The GTK stopwatchIf the button is set up to call start when you click it, and you call signal_ connect('clicked',proc { stop }), then clicking on the button will call start and then call stop. You've added a second code block to the "clicked" event, when what you want is to replace the old "clicked" code with the new code. To avoid this problem, set_button_handler removes any old handler from the button before installing the new handler. The set_button_handler method tracks the internal ID of the newly installed handler, so that it can be removed if the user clicks the button yet again. See Also
|
< Free Open Study > |
16.1. Selecting the Kind of LoopIn most languages, you'll use a few kinds of loops:
The kinds of loops are differentiated first by flexibility�whether the loop executes a specified number of times or whether it tests for completion on each iteration. The kinds of loops are also differentiated by the location of the test for completion. You can put the test at the beginning, the middle, or the end of the loop. This characteristic tells you whether the loop executes at least once. If the loop is tested at the beginning, its body isn't necessarily executed. If the loop is tested at the end, its body is executed at least once. If the loop is tested in the middle, the part of the loop that precedes the test is executed at least once, but the part of the loop that follows the test isn't necessarily executed at all. Flexibility and the location of the test determine the kind of loop to choose as a control structure. Table 16-1 shows the kinds of loops in several languages and describes each loop's flexibility and test location.
When to Use a while LoopNovice programmers sometimes think that a while loop is continuously evaluated and that it terminates the instant the while condition becomes false, regardless of which statement in the loop is being executed (Curtis et al. 1986). Although it's not quite that flexible, a while loop is a flexible loop choice. If you don't know ahead of time exactly how many times you'll want the loop to iterate, use a while loop. Contrary to what some novices think, the test for the loop exit is performed only once each time through the loop, and the main issue with respect to while loops is deciding whether to test at the beginning or the end of the loop. Loop with Test at the BeginningFor a loop that tests at the beginning, you can use a while loop in C++, C#, Java, Visual Basic, and most other languages. You can emulate a while loop in other languages. Loop with Test at the EndYou might occasionally have a situation in which you want a flexible loop, but the loop needs to execute at least one time. In such a case, you can use a while loop that is tested at its end. You can use do-while in C++, C#, and Java, Do-Loop-While in Visual Basic, or you can emulate end-tested loops in other languages. When to Use a Loop-With-Exit LoopA loop-with-exit loop is a loop in which the exit condition appears in the middle of the loop rather than at the beginning or at the end. The loop-with-exit loop is available explicitly in Visual Basic, and you can emulate it with the structured constructs while and break in C++, C, and Java or with gotos in other languages. Normal Loop-With-Exit LoopsA loop-with-exit loop usually consists of the loop beginning, the loop body (including an exit condition), and the loop end, as in this Visual Basic example: Visual Basic Example of a Generic Loop-With-Exit Loop
The typical use of a loop-with-exit loop is for the case in which testing at the beginning or at the end of the loop requires coding a loop-and-a-half. Here's a C++ example of a case that warrants a loop-with-exit loop but doesn't use one: C++ Example of Duplicated Code That Will Break Down Under Maintenance
The two lines of code at the top of the example are repeated in the last two lines of code of the while loop. During modification, you can easily forget to keep the two sets of lines parallel. Another programmer modifying the code probably won't even realize that the two sets of lines are supposed to be modified in parallel. Either way, the result will be errors arising from incomplete modifications. Here's how you can rewrite the code more clearly: C++ Example of a Loop-With-Exit Loop That's Easier to Maintain
Here's how the same code is written in Visual Basic: Visual Basic Example of a Loop-With-Exit Loop' Compute scores and ratings Consider these finer points when you use this kind of loop: Put all the exit conditions in one place. Spreading them around practically guarantees that one exit condition or another will be overlooked during debugging, modification, or testing. Cross-Reference Details on exit conditions are presented later in this chapter. For details on using comments with loops, see "Commenting Control Structures" in Section 32.5. Use comments for clarification. If you use the loop-with-exit loop technique in a language that doesn't support it directly, use comments to make what you're doing clear.
In common practice, the loop-with-exit loop isn't widely used yet. The jury is still locked in a smoky room arguing about whether it's a good practice for production code. Until the jury is in, the loop-with-exit loop is a good technique to have in your programmer's toolbox�as long as you use it carefully. Abnormal Loop-With-Exit LoopsAnother kind of loop-with-exit loop that's used to avoid a loop-and-a-half is shown here:
At first glance, this seems to be similar to the previous loop-with-exit examples. It's used in simulations in which // do something doesn't need to be executed at the first pass through the loop but // do something else does. It's a one-in, one-out control construct: the only way into the loop is through the goto at the top, and the only way out of the loop is through the while test. This approach has two problems: it uses a goto, and it's unusual enough to be confusing. In C++, you can accomplish the same effect without using a goto, as demonstrated in the following example. If the language you're using doesn't support a break command, you can emulate one with a goto. C++ Example of Code Rewritten Without a goto�Better Practice
When to Use a for LoopA for loop is a good choice when you need a loop that executes a specified number of times. You can use for in C++, C, Java, Visual Basic, and most other languages. Further Reading For more good guidelines on using for loops, see Writing Solid Code (Maguire 1993). Use for loops for simple activities that don't require internal loop controls. Use them when the loop control involves simple increments or simple decrements, such as iterating through the elements in a container. The point of a for loop is that you set it up at the top of the loop and then forget about it. You don't have to do anything inside the loop to control it. If you have a condition under which execution has to jump out of a loop, use a while loop instead. Likewise, don't explicitly change the index value of a for loop to force it to terminate. Use a while loop instead. The for loop is for simple uses. Most complicated looping tasks are better handled by a while loop. When to Use a foreach LoopThe foreach loop or its equivalent (foreach in C#, For-Each in Visual Basic, for-in in Python) is useful for performing an operation on each member of an array or other container. It has the advantage of eliminating loop-housekeeping arithmetic and therefore eliminating any chance of errors in the loop-housekeeping arithmetic. Here's an example of this kind of loop: C# Example of a foreach Loopint [] fibonacciSequence = new int [] { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 }; |
< Free Open Study > |