</script> tags. Listing 1 displays the Hello, World text:
Listing 1. Hello, world
To run the code, just create a file called example1.html, copy Listing 1 into the file, and load the file in your browser. (See Download for all the example HTML files for this article.) You'll notice that the code immediately executes each time you reload the page.
Figure 1. Hello, world
<head> element, as in Listing 2:
Listing 2. Delaying execution
Type the code in Listing 2 into an HTML file, load the file in your browser, and click the Say Hello button for the result shown in Figure 2:
Figure 2. Delaying execution
Listing 3. Manipulating functions with variables
cold. I store each in a variable. Clicking the Hot or Cold button invokes the appropriate function, generating an alert. Next, I declare a function that swaps the values of the Hot and Cold buttons, attaching this function to a third button that displays the alert shown in Figure 3:
Figure 3. Manipulating functions
Using a function as a function argument, or returning a function as a value, elevates this abstraction into the realm of higher-order functions. Listing 4, a slight modification of Listing 3, shows a higher-order function that returns a function:
Listing 4. Higher-order functions
This example solves a common problem: how do you attach changing behavior to a user interface event? With a higher-order function, it's easy. The
temperature higher-order function returns the value of
current, which has either the
cold function. Look at the rather odd-looking invocation of the function:
temperature()(). The first set of parentheses is needed to invoke the
temperature function. The second invokes the function returned by
temperature. Figure 4 shows the output:
Figure 4. Higher-order functions
With static typing, the compiler can check the values of arguments, variables, or return values against values allowed for a given operation. The benefit is additional error checking by a compiler. Also, static typing provides more information for tools such as IDEs, allowing features such as better code completion. However, static typing has several drawbacks:
- You must declare your intentions earlier, which often leads to reduced flexibility. For example, changing a Java class also changes that class's type, forcing a recompile. In contrast, Ruby allows open classes, but changing a class also changes that class's type.
- You must often enter more code to express equivalent ideas. For example, you must include type information with arguments, return values with functions, and types for all variables. You must also declare all variables and explicitly convert between types.
- The compile-deploy cycle often takes longer than development cycles for similar dynamic languages, though tools can sometimes mitigate this problem somewhat.
First, consider an object. In Listing 5, I create a new object and access a nonexistent attribute called
Listing 5. Introducing an attribute
When you load the application and execute it, you get the result in Figure 5:
Figure 5. Introducing attributes
blue attribute does not exist. Proponents of static languages are horrified at this example, seeing the ripe potential for errors. Although it may make you feel dirty, you can't deny the appeal. You can quickly introduce attributes. And combining this example with the earlier examples in this article, you can also introduce behavior. Remember, variables can hold functions! So based on the dynamic typing and higher-order functions, you can introduce arbitrary behavior to your classes at any time.
I can easily rewrite Listing 5 as Listing 6:
Listing 6. Introducing behavior
The Java language is class-based. When you build applications, you build a new class as a template for all objects. Then, you call
I'll break away from the abstract to show you some working code. To start, Listing 7 creates a simple
Animal having an attribute of
name and an action of
speak. Then, other animals will inherit from this base.
Listing 7. Creating a constructor
Listing 7 produces the example in Figure 6:
Figure 6. Creating a constructor
funct() is an invocation, but
new Animal() constructs an object based on the prototype in
myAnimal, based on the prototype you specify in
Animal. You can then use the attributes and functions in your prototype, or even redefine the functions or attributes. This flexibility can be maddening to Java developers, who are not accustomed to this behavior, but it's quite a powerful model.
I'm going to turn things up a notch now. You can use the instance variable called
prototype to specify the basis for your object. You'll set a
prototype instance variable to point to the parent in the inheritance chain. If you set
prototype, objects you create will inherit attributes and functions for any that you fail to specify. In this way, you can simulate the object-oriented concept of inheritance. Take Listing 8, for example:
Listing 8. Inheritance with prototypes
In Listing 8, I create a
Dog prototype. I base that prototype on
Dog redefines the
speak() method but does nothing for the
name() method. Then, I set the prototype of
Animal. Figure 7 shows the result:
Figure 7. Inheritance with prototypes
- You can redefine the variables in your object just like any other variable. By doing so, you will, of course, change your object. So any attributes or functions you explicitly define take precedence over those defined in your original prototype.
- If you explicitly set the instance variable called
prototypecannot find an attribute or function, it will look in its prototype, and so on.
In other ways, this flexibility is also a great blessing. The Java language has long suffered from escalating complexity because the base object model is not flexible enough to be extended. Great open source projects and new technologies such as aspect-oriented programming, the Spring programming framework, and bytecode-enhancement libraries add mountains of code to the things a typical enterprise developer must learn to wield the Java language successfully.
|Sample HTML files for this article||j-cb12196.zip||3KB||HTTP|
- Java To Ruby: Things Every Manager Should Know (Pragmatic Bookshelf, 2006): The author's book about when and where it makes sense to make a switch from Java programming to Ruby on Rails, and how to make it.
- Beyond Java (O'Reilly, 2005): The author's book about the Java
language's rise and plateau and the technologies that could challenge the Java platform in some niches.
- The Java technology zone: Hundreds of articles about every aspect of Java programming.
- Ajax Resource Center: Your destination for everything Ajax on developerWorks.
Bruce Tate is a father, mountain biker, and kayaker in Austin, Texas. He's the author of three best-selling Java books, including the Jolt winner Better, Faster, Lighter Java. He recently released From Java to Ruby and Rails: Up and Running. He spent 13 years at IBM and later formed the RapidRed consultancy, where he specialized in lightweight development strategies and architectures based on Ruby, and in the Ruby on Rails framework. He is now the CTO of WellGood LLC, a company that is forming a marketplace for nonprofit organizations and charitable giving.