22
Sun, Dec
3 New Articles

Object-oriented Design for AS/400 Java Applications: Java Interfaces

Java
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Interfaces are a Java construct that make programming powerful applications easy. Designing to an interface is a strategy that all object-oriented programmers should employ, but Java is the only language that makes the process easy. This article will show why Java interfaces allow our Java classes to be flexible, extensible, and pluggable.

There is a new strategy in object-oriented programming; it’s called designing to an interface. The idea of this strategy is to forget about using complex hierarchies of classes and to focus on the common interfaces of classes. (Remember that a class’s interface is its list of public—and protected—functions.) With inheritance, the interface of a base class as well as its implementations are passed on to its subclasses. However, Java classes don’t always share the same functions and implementations of other classes. When your classes share functions of the same name but not necessarily the same implementations of other classes, using an interface can simplify your programming efforts.

When you design to an interface using Java’s inheritance, you write your derived classes to use the functional interfaces of your base classes. Java’s polymorphism (I’ll define this term later in the article) then kicks in to call the proper subclass implementation of the base class’s interface. If you feel as though you’re pushing your understanding of object-oriented programming right now, it’s OK because Java has an alternative approach, designing to an interface, that is more intuitive than inheritance. This article covers the approach to designing to an interface, first with Java’s intuitive method and then, after introducing you to the concepts of polymorphism, with the inheritance method.

Java has a construct that supports designing to an interface more clearly than any other object-oriented language. Even with the sophisticated language of C++, programmers have to bend over backwards to simulate what Java does effortlessly. This Java construct is aptly called an interface. Java interfaces allow you to associate a set of function names that serve a similar or related purpose into a discretely named unit. The difference between a Java interface and a Java class is that the functions of an interface are without implementations.

The ITransaction interface in Figure 1 is composed of functions typically associated with transactions, such as setting and getting the date, quantity, cost, and description of a transaction. At a first glance, you’d think that an interface is pretty much the same thing as a class. But if you look more closely, you’ll notice that the ITransaction interface contains no code implementations for its functions. You might also notice that the interface does not declare the date, description, cost, or quantity fields that its functions presumably get and set.

A Java interface is a standard protocol that is used as a consistent API for behaviors that are common to a variety of classes. For instance, as you design an object model, you may find that you are defining the same printing functions in classes that represent dissimilar entities. So, you develop an IPrint interface such as the one shown at the top of Figure 1. That interface then serves two purposes: First, it defines the protocol for the implementation of a printable interface. Second, any object that has an implementation for the printable interface can be used as a runtime IPrint object via polymorphism. There’s that 10-dollar word again, and I promise I’ll cover it, but first I need to show you how to implement an interface.

You can see in Figure 2 that the purchase order (POActivity) class implements the ITransaction interface. When you design a class that implements an interface, you must provide code implementations for all of the functions inherited from that interface. As a result, the POActivity class has code for all of the functions declared in the ITransaction interface. Note that to implement the ITransaction interface, the POActivity class had to define functions with the exact name, return type, and number and type of arguments—that is, the same signature as those of the ITransaction interface.

If you look at the Unified Modeling Language (UML) diagram in Figure 3, you’ll notice that the POActivity class declares those date, description, quantity, and cost fields that the functions of the ITransaction interface implied. It may seem to you that it would have been clearer had I put those four fields directly in the ITransaction interface. But Java interfaces don’t support the declaration of fields. And, when you think about it, if you could put fields in an interface, it would be as if you were defining an entity (that is, a real- world object that has a state and identity). An interface is not an entity; it is only a list of functions, merely a protocol that is a standard way of communicating. Because the creators of Java did not want interfaces to represent entities, an interface can never be instantiated as an object. You couldn’t, for example, code the following:

ITransaction trans = new ITransaction(); Actually, I lied. You can declare a field in a Java interface, but that field is implicitly qualified as static and final. (Note that the fields and the functions of an interface are also implicitly public.) The static and final qualifiers effectively make the fields of an interface constants because their values cannot be modified; they are immutable. Because fields of an interface are immutable, their values must be initialized as a part of its definition as the class field called RED in the IColor interface of Figure 4. Realize that, although the IColor interface has fields, IColor still does not represent an entity because the fields are constants. You’ll find that the most common use of interface fields is for default values.

Inheritance Versus Interfaces

The Java ITransaction interface of Figure 1 could have been developed instead as a class called Transaction, and that class could then have been a superclass for the work order (WOActivity) and purchase order (POActivity) classes. But as the object model in Figure 3 shows, the WOActivity class already has a base class. Java classes can only have one parent, so WOActivity couldn’t extend a Transaction class. Even so, WOActivity does implement two interfaces: ITransaction and IPrint. A big advantage of interfaces over inheritance is that, although a class can extend only one parent class, a class can implement multiple interfaces. The UML notation, by the way, for implementing an interface is a dotted line, and an interface is differentiated from a class with the word interface at the top of a box.

If you look at the Java code for the WOActivity class’s implementations of the ITransaction interface in Figure 2, you’ll notice that is varies from those of the POActivity class. (Note that the integer representations for badge would probably have been implemented in a real system by an Employee class that encapsulates the attributes and behaviors of an employee.) That’s another reason to use interfaces rather than inheritance: When implementations of an interface are going to vary from class to class, it doesn’t make sense to put code implementations for those functions in a base class. If you remember from the most recent article of this series [see “Object-oriented Design for AS/400 Java Applications: Inheritance,” MC, October 1998], Java does allow you to override the implementation of a function inherited from a parent class, but inheritance works best when the code implementation of a base class fits the requirements of its subclasses.

What’s the Big Deal?

The ability to define a standard protocol with a Java interface is all well and good, but that ability alone is nothing more than an enforced naming convention. The big deal comes from the flexibility, extensibility, and pluggability that interfaces give us. Interfaces are flexible because they allow you to change the implementation of an interface based on varied requirements of classes. As I will explain, they are extensible because you can string multiple interfaces in the definition of a class. And they are pluggable because, as I will show you, the classes that implement the same interface can be used interchangeably.

Extensibility

Complex interfaces with lots of functions can often be simplified by dividing them into several small interfaces. The ITransaction interface of Figure 1, for instance, could be further divided into IDate, IDescription, IQuantity, and ICost interfaces. An entirely new- looking (but functionally equivalent) ITransaction interface is shown in Figure 5 that is a composite interface of the four components of the ITransaction interface. This variety of interfaces also serves to further protect the internals of objects by giving other objects access only to a specific interface.

Pluggability

It follows that a class (such as the WOActivity class) that implements an interface can then be instantiated as an object. That object can then invoke the functions that were implemented in that class but defined in the interface:

WOActivity woActive = new WOActivity(); woActive.setDescription(“Widget polished”); The pluggability of the interfaces of WOActivity will become evident to you when you see that you can assign the reference to that WOActivity object to a variable that is typed as an interface:

ITransaction trans = woActive; Earlier, I said that you can never instantiate an interface. You can, however, declare the type of a variable as an interface and assign to that interface variable a reference to any object whose class implemented that variable’s interface. The interface variable may then invoke the functions that were defined in its interface. For instance, the trans interface variable can invoke setDescription, but it cannot invoke printHeader. That’s because, even though printHeader is a part of the WOActivity class that the woActive object was originally instantiated as, printHeader is not a part of the ITransaction interface. The trans variable, because it is constrained by the functions of the object type of its ITransaction object type, cannot invoke the printHeader function.

It may sound as if interface variables are used to limit the scope of objects, but they actually make Java more powerful. As I will show you, the ability to reference objects with an interface variable makes objects that implement interfaces very pluggable.

The Many Faces of an Interface

The TestTransaction application class of Figure 6 illustrates the pluggability of interfaces. The PrintTransaction utility class illustrates polymorphism (I told you I’d define this term).

Polymorphism means, literally, “many changes.” As I’ll explain, the function implementations of the ITransaction interfaces go through a metamorphosis several times in the PrintTransaction class. TestTransaction’s main function bootstraps the application by creating itself by invoking its constructor function with Java’s new operator. The constructor function, TestTransaction, creates a POActivity object and invokes its implementation of the setDescription function inherited from the ITransaction class.

Then, TestTransaction creates a WOActivity object and invokes its implementations of several of the inherited functions of the ITransaction class. So far, no new Java strategies have arisen, but TestTransaction then creates two ITransaction variables and sets them to reference objects whose class implemented the ITransaction interface. Remember, you cannot instantiate an interface as an object:

ITransaction trans = new ITransaction(); // compile error However, you can assign a reference to an object that was created from a class that implemented the same interface as a variable typecast as that interface:

POActivity po = new POActivity(); ITransaction trans1 = po; This process is sometimes called downcasting because the object referenced with the variable po was typecast as member of the POActivity class, but because the POActivity class also is a type of ITransaction, we can assign that object’s reference to an ITransaction variable. Because the trans interface variable was less than that of a POActivity class variable, you can say that we downcast a POActivity variable to an ITransaction variable.

The TestTransaction function then prints the description of the transaction using the interface variables. It would have been easier to have simply invoked the getTransaction functions directly from the wo or po variables:

System.out.println(wo.getDescription()); But by using the interface variables, I have given you a hint of the power of interfaces and the polymorphic behavior of objects. You now can see that, although the trans1 and trans2 variables are not of the POActivity or WOActivity class, they invoke the functions that were implemented in those classes.

The last three Java statements of the TestTransaction function further illustrate the polymorphic behavior of interfaces. The printGroup variable is an array that is typecast as IPrint. The array is initialized to reference the two POActivity and WOActivity objects. Then a PrintTransactions object is instantiated. Note that the constructor for PrintTransaction opens the selected output medium. The printGroup array is then passed to PrintTransactions’s print function, which spins through the array and invokes each of the functions of the IPrint interface.

The PrintTransaction class and its print function have been designed to an interface. Rather than your writing a function to print work-order transactions, and then writing a function to print purchase-order transactions, and then writing, well, you get the idea—you write one function that is designed to use the IPrint interface. The PrintTransaction class can handle the printing of any class that implements the IPrint interface. Figure 7 shows the result of running the TestTransaction application.

The Power of Interfaces

Even if you never design a single Java interface, you will, nonetheless, be using them. Java interfaces are heavily used in the implementation of Java itself. Interfaces are used in two areas in particular: Java’s GUI event-handling mechanism and Java’s Remote- Method-Invocation (RMI) facility.

Java interfaces are also heavily used in many of the standard Java packages, such as the Abstract Windowing Toolkit (AWT). When you develop a Java GUI with AWT, you group window components such as buttons, text boxes, and list boxes into a window. Each of these components can generate a variety of events, such as the button being clicked or text being entered into the text box or an element of the list box being selected with the mouse. Each of these events has an associated AWT interface.

You design your Java application to handle these events by creating classes that implement the standard AWT interfaces. Object instances of the classes that implement the AWT interfaces are then registered with a component so that they can react to events generated by that component. You don’t code calls to those functions; the Java Virtual Machine (using polymorphism) automatically does that for you by invoking your class’s code implementation of the AWT interface. Because these interfaces are common, you can obtain Java classes that implement these standard interfaces from a wide variety of sources—other teams, Internet freeware, and third-party suppliers—once again displaying the pluggability of interfaces.

Another example of the power and versatility of interfaces is RMI, which is Java
1.1’s strategy for distributed computing. Remote access to objects residing on host machines is enabled through an interface. You pull the functions of a host class that require remote access into a Java interface. Then, with the magic of RMI, a Java application on a client machine can declare a variable to be of the interface type and assign to that variable a reference to the object on the host machine that implements the interface.

The other day, my wife said to one of our sons: “That’s what you get for being a member of my side of the family.” She laughed and quickly corrected her statement because it sounded as if she were saying that my son had inherited attributes only from her. But I thought, hey, that’s Java inheritance—only one parent. What, then, would be the human analogy to Java interfaces?

Human behavior allows us to interface with others using such qualities as character, style, and skill. These qualities are not inherited; they are acquired: You provide your own implementation of character, style, and skill. If my sons (who are trying to develop a class of their own) were adequately familiar with Java and would actually listen to me, my directions to them would be to implement a character, implement a style, and implement a skill (Figure 8). They already have the inherited attributes of intelligence and creativity, as well as self-preservation and desire. I could tell them to develop multiple interfaces so that, like a Java class, they can have many interfaces and others would be able to interface with them in a variety of ways to satisfy their particular needs.

For instance, I have my own implementations for the IProgrammer, IWriter, or IMakeSandwiches interfaces. When my sons use my IMakeSandwiches interface, they have only one need in mind. In other words, they don’t care about my IProgrammer implementation—they just want a good sandwich.

// the IPrint interface public interface IPrint {

// note, all functions of an interface // are implicitly public void printHeader(); void printDetail(); void printFooter();

}

// The ITransaction interface import java.util.Date; public interface ITransaction { Date getDate(); String getDescription(); int getQuantity (); BigDecimal getCost (); void setDate(Date date);

void setDescription(String desc); void setQuantity (int qty); void setCost(BigDecimal cost);

}

Figure 1: The transaction and print interfaces, as with all Java interfaces, have no code implementations

public class POActivity extends rdbPOActivity implements ITransaction {

private java.util.Date date;

private String description;

private int quantity;

private String shipMethod;

public java.util.Date getDate() {return date;}

public String getDescription() {return description;}

public int getQuantity() {return quantity;}

public void setDate(Date date) {this.date = date;}

public void setDescription(String desc) {description = desc;}

public void setQuantity(int qty) {quantity = qty;}

public void setShipMethod(String shipMethod) {this.shipMethod = shipMethod;} }

public class WOActivity extends rdbWOActivity implements ITransaction, IPrint {

private java.util.Date date;

private String description;

private int quantity;

private int shift;

private int badge;

// ITransaction interface:

public java.util.Date getDate() {return date;}

public String getDescription() {

return "badge no: "+badge+ " shift: "+shift+" "+description;

}

public int getQuantity() { return quantity;}

public void setBadge (int badge) { this.badge = badge;}

public void setDate(Date date) { this.date = date;}

public void setDescription(String desc) { description = desc;}

public void setQuantity(int qty) { quantity = qty;}

public void setShift (int shift ) { this.shift = shift;}

// IPrint interface

public void printHeader() {}

public void printDetail(){}

public void printFooter(){} }

Figure 2: The POActivity and the WOActivity classes both implement the transaction interface




Figure 3: The UML object model shows how the same interface can be implemented in dissimilar objects


ainterface IColors {

// implicit public static final int RED = 1; // the public static final qualifiers are not necessary // because they will be added by the compiler

public static final int GREEN = 2;

// implicitly public

void int getColor();

// the public qualifier is not necessary // because it will be added by the compiler

public int setColor(int color); }

Figure 4: Java interfaces can declare fields, but they are implicitly qualified as static, final, and public; therefore, they are effectively constants

// example of a composite interface interface IDate {

Date getDate(); void setDate(Date date);



Object-_oriented_Design_for_AS-_400_Java_...07-00.png 891x525

}

interface IDescription {

String getDescription(); void setDescription(String desc); }

interface IQuantity { int getQuantity (); void setQuantity (int qty); }

interface ICost { void setCost(BigDecimal cost); BigDecimal getCost ();

}

interface ITransaction extends IDate, IDescription, IQuantity, ICost {} Figure 5: Interfaces can be combined into one composite interface

public class TestTransactions {

public TestTransactions () {

POActivity po = new POActivity();

po.setDescription("purchase order shipped");

WOActivity wo = new WOActivity();

wo.setDescription("W/O routing step 110 completed");

wo.setDate(new java.util.Date());

wo.setBadge(928);

ITransaction trans1 = po;

ITransaction trans2 = wo;

System.out.println(trans1.getDescription());

System.out.println(trans2.getDescription());

IPrint[] printGroup = {po, wo};

PrintTransactions print =

new PrintTransactions(PrintTransactions.FILE);

print.print(printGroup);

}

public static void main(java.lang.String[] args) {

new TestTransactions();

}

}

public class PrintTransactions {

public void print(IPrint[] printGroup) {

for (int i = 0; i < printGroup.length; i++) {

printGroup[i].printHeader();

printGroup[i].printDetail();

printGroup[i].printFooter();

}

}

}

Figure 6: Java’s polymorphism adapts code at runtime to invoke the various implementations of interfaces by dissimilar objects

purchase order shipped Mon Jun 15 21:23:27 EDT 1998 Badge: 928 Desc: W/O routing step 110 completed Purchase Order Activity:
purchase order shipped
*** POActivity Footer ***
Work Order Activity: Mon Jun 15 21:23:27 EDT 1998 Badge: 928 Desc: W/O routing step 110 completed *** WO Footer *** Figure 7: The Java Virtual Machine, via polymorphism, dynamically handles the behavior of various implementations of the ITransaction interface

class Denoncourt { int intelligence, creativity; // [editorial license] }

class DonDenoncourt extends Denoncourt implements ICharacter, IStyle, IProgrammer, IWriter, IMakeSandwiches {

...// implementations of interfaces }

class JoshuaDenoncourt extends Denoncourt implements ICharacter, IStyle, IArtist, IWriter {

// implementations of interfaces:
...

// note that JoshuaDenoncourt's implementation of character, style and writer // are completely different from DonDenoncourt's, even if the interface is the // same. JoshuaDenoncourt also implements an artist interface
...

// interfacing with others, // JoshuaDenoncourt usually uses the DonDenoncourt implementation // of IMakeSandwiches to get a sandwich but he also uses // Subway or other IMakeSandwiches implementations

void getSandwich(IMakeSandwiches chef) { chef.getSandwich();

}

}

Figure 8: Individuals may inherit characteristics from their parents, but to interface with the world, they have to implement their own character, style, and skill

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: