O'Reilly Databases

oreilly.comSafari Books Online.Conferences.

We've expanded our coverage and improved our search! Search for all things Database across O'Reilly!

Search Search Tips

advertisement
AddThis Social Bookmark Button

Listen Print Subscribe to Databases Subscribe to Newsletters

Inherit the Database: Oracle9i's Support for Object Type Inheritance
Pages: 1, 2, 3, 4, 5

An Example of Dynamic Polymorphism

Let's take a look at how I can take advantage of dynamic polymorphism with my hierarchy of different types of persons. I need to write a program to show what happens when different types of persons (which, in the U.S., include corporations by legal precedent) commit a crime. I'll walk through the individual steps for such a program.

First, I'll define my different types of persons:

  1. A pre-citizenship person, Eve:

       eve person_ot
       := person_ot (
             'Human',
             'Eve',
             175 /* Rubanesque */,
             NULL
          );
  2. A U.S. citizen who's currently on death row for murder, but is believed by many to be innocent of the crime (or at least to have received a grossly unfair trial). Notice that I add two additional attributes for a citizen, nation, and political preference.

       ondeathrow citizen_ot
       := citizen_ot (
             'Human',
             'Mumia Abul Jamal',
             150,
             NULL,
             'USA',
             'Radical' 
          );
  3. A very scary company, the likes of which we're likely to see in the next decade or so with the way mergers and acquisitions are proceeding these days:

       theglobalmonster corporation_ot
       := corporation_ot (
             'Inhuman',
             'Northrup-Ford-Mattel-Yahoo-ATT',
             NULL,
             SYSDATE,
             5000000,
             50000000
          );
  4. An even scarier human being, defined as a war criminal for his direction of the carpet- bombing of Vietnam and Cambodia:

       wiseman warcriminal_ot
       := warcriminal_ot (
             'Human?',
             'Henry Kissinger',
             175,
             NULL,
             'USA',
             'Above the law',
             1000000,
             'Vietnam and Cambodia'
          );

I've now defined four different objects, instantiated from different types in the person hierarchy: person, citizen, corporation, and war criminal. Now for the really interesting stuff. I want to define an array or list that contains all of these objects and then manipulate the contents of that array. Since all of the objects derive from the person supertype, I can declare a nested table of persons and populate that array with either person objects or objects declared from subtypes of person:

   TYPE bighappyfamily_nt IS TABLE OF person_ot;

   bighappyfamily bighappyfamily_nt
   := bighappyfamily_nt (
         eve,
         ondeathrow,
         theglobalmonster,
         wiseman
      );

I've now completed my declarations. On to my executable section. What I need to do is show what happens to each "person" when he or she commits a crime. What political power do they have and what is their punishment? To do that I can simply execute the following loop:

BEGIN
   FOR persindx IN
       bighappyfamily.FIRST .. bighappyfamily.LAST
   LOOP
      DBMS_OUTPUT.PUT_LINE (' ');
      bighappyfamily (persindx).when_crime_committed;
   END LOOP;
END;

The output from this loop's execution is shown in Listing 4. It all looks perfectly appropriate. For each different type of person, the information displayed is specific to that object. Yet quite a lot is going on behind the scenes to make that happen. Let's take a closer took.

Listing 4. Output from displaying the contents of the bighappyfamily array.

Suppose Eve Was Convicted of a Crime.--
Person named Eve weighs 175 and was born on
Political power?
The existence of a soul
Punishment?
Leave Garden of Eden

--Suppose Mumia Abul Jamal Was Convicted of a Crime.--
Citizen Mumia Abul Jamal is a citizen of USA whose politics are Radical
Political power?
One vote
Punishment?
Go to jail, do not pass Go, do not survive.

--Suppose Northrup-Ford-Mattel-Yahoo-ATT Was Convicted of a Crime.--
Corporation Northrup-Ford-Mattel-Yahoo-ATT is a trans-national entity with
50000000 laid-off employees, paying its Chief Executive Officer 5000000
Political power?
Virtually unlimited
Punishment?
Increased political contributions.

--Suppose Henry Kissinger Was Convicted of a Crime.--
War criminal Henry Kissinger killed 1000000 in Vietnam and Cambodia
Political power?
Filling the vacuum.
Punishment?
Sometimes you win the Nobel Peace Prize.

My FOR loop iterates through every row of bighappyfamily. Recall that bighappyfamily is a nested table of persons. Within the FOR loop, I invoke the when_crime_committed method for each element in the array. The when_crime_committed method is declared as FINAL in the person object and implemented as follows:

FINAL MEMBER PROCEDURE when_crime_committed
IS
BEGIN
   DBMS_OUTPUT.PUT_LINE (   '--Suppose '
     || name
     || ' Was Convicted of a Crime.--');
   DBMS_OUTPUT.PUT_LINE (' ');
   show;      
   DBMS_OUTPUT.PUT_LINE (' ');
   DBMS_OUTPUT.PUT_LINE ('Political power?');
   showPoliticalPower;
   DBMS_OUTPUT.PUT_LINE (' ');
   DBMS_OUTPUT.PUT_LINE ('Punishment?');
   showpunishment;
END;

By defining the method as FINAL, I disallow any of the subtypes of person to override this program. Notice, however, that when_crime_committed invokes three other methods: show, showPoliticalPower and showPunishment. None of these methods, defined in person_ot, are defined as FINAL and, in fact, are overridden in each of the object types citizen_ot, corporation_ot, and war_criminal_ot. Here's one example of such an override, the citizen.showPoliticalPower method:

OVERRIDING 
   MEMBER PROCEDURE 
      showpoliticalpower
IS
BEGIN
   DBMS_OUTPUT.PUT_LINE (
      'One vote');
END;

So, at the time of compilation of the person_ot object type, references to the show, showPoliticalPower, and showPunishment methods are all resolved to the person_ot methods. But when the when_crime_committed method is actually executed by the PL/SQL runtime engine, dynamic method dispatch results in a very different resolution.

When Oracle executes the following method, for example:

bighappyfamily(3).when_crime_committed

it identifies the object type as corporation_ot. Then it checks to see whether when_crime_committed is defined as a method in corporation_ot. It's not and, in fact, is only defined in person_ot. So the runtime engine then invokes person.when_crime_committed. As it runs that method, it encounters the showPoliticalPower method. Once again, Oracle must identify which of the showPoliticalPower methods to run. Even though it's currently executing a person_ot method, it hasn't forgotten where it came from. It therefore starts its search through the hierarchy with the corporation_ot object type. And, in fact, it finds that corporation_ot has implemented an overriding showPoliticalPower method. So it uses that one and not the person_ot.show method.

There are two approaches to resolving invocations to methods, static and dynamic.

Also In This Series

Substituting and Converting Object Types in a Hierarchy

New Datatypes, New Possibilities

Native Compilation, CASE, and Dynamic Bulk Binding

Table Functions and Cursor Expressions

Multi-Level Collections in Oracle 9i

HTTP Communication from Within the Oracle Database

Oracle 9i Release 2 Developments for PL/SQL Collections

Using PL/SQL Records in SQL Statements

Dynamic polymorphism gives developers an incredible amount of flexibility. We can write generalized programs that seemingly overlook variations in subtypes and levels in the hierarchy. We leave it to the runtime engine to locate and execute the most appropriate definition of a method.

It's Time to Try Out Object Types

Prior to Oracle9i, there was no compelling reason to use object types unless you used Oracle Advanced Queuing or some other Oracle utility that relied on object types. There were simply too many limitations to its implementation. With Oracle9i and the support for inheritance, however, Oracle takes PL/SQL a big step closer to a true object-oriented language.

Now that we can set up object-type hierarchies, it's worth revisiting object types to see how they can be used to construct robust applications based on PL/SQL. We'll explore further nuances of inheritance in the next article.

This article was originally published in the December 2001 issue of Oracle Professional. The material in Feuerstein and Bryn Llewellyn's articles is based on Oracle Corporation white papers originally prepared by Llewellyn for Oracle OpenWorld 2001 in San Francisco and OracleWorld Copenhagen in June 2002 and Oracle PL/SQL Programming, 3rd Edition.

Steven Feuerstein is considered one of the world's leading experts on the Oracle PL/SQL language, having written ten books on the subject. Steven is a Senior Technology Advisor with Quest Software and has been developing software since 1980.


O'Reilly & Associates recently released (September 2002) Oracle PL/SQL Programming, 3rd Edition.

  • Sample Chapter 10, Dates and Timestamps , is available free online.

  • You can also look at the Table of Contents, the Index, and the Full Description of the book.

  • For more information, or to order the book, click here.

Oracle PL/SQL Programming

Related Reading

Oracle PL/SQL Programming
By Steven Feuerstein

Return to the O'Reilly Network.




Tagged Articles

Be the first to post this article to del.icio.us

Sponsored Resources

  • Inside Lightroom

Related to this Article

Understanding Oracle Clinical Understanding Oracle Clinical
by Joan M. Johnson
June 2009
$9.99 USD

New Features in Oracle 9i New Features in Oracle 9i
by Howard J. Rogers
June 2009
$5.95 USD

Advertisement
O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com