Inherit the Database: Oracle9i's Support for Object Type Inheritance
Pages: 1, 2, 3, 4, 5
Implementing the Object Type Body
Let's now take a look at the body of the person type, shown in Listing 2.
Listing 2. Body of person_ot object type.
CREATE OR REPLACE TYPE BODY person_ot
IS
MEMBER PROCEDURE show
IS
BEGIN
DBMS_OUTPUT.PUT_LINE ('Person named ' || SELF.name ||
' weighs ' || SELF.weight ||
' and was born on ' || SELF.dob);
END;
-- My wife has been reading Milton's Paradise Lost, so:
MEMBER PROCEDURE showpunishment
IS
BEGIN
DBMS_OUTPUT.PUT_LINE ('Leave Garden of Eden');
END;
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;
FINAL MEMBER FUNCTION age RETURN INTERVAL YEAR TO MONTH
IS
retval INTERVAL DAY TO SECOND;
BEGIN
RETURN (SYSDATE - SELF.dob) YEAR TO MONTH;
END;
OVERRIDING MEMBER PROCEDURE showpoliticalpower
IS
BEGIN
DBMS_OUTPUT.PUT_LINE ('The existence of a soul');
END;
END;
/
From a programming standpoint, there isn't much to note in the person_ot body. It
mostly displays information (show displays the characteristics of a person,
showpunishment shows the punishment a person receives when he or she commits a crime,
and so on). The FINAL when_crime_committed calls a number of other programs (show, showpoliticalpower, showpunishment) and will figure prominently later in our analysis of the way PL/SQL determines which method in the hierarchy to execute.
The age function should catch your attention, as it makes use of the new INTERVAL datatype to compute the difference between two dates. You can define two types of
INTERVALS:
DAY TO SECOND: Represent the precise difference between two datetime values.YEAR TO MONTH: Calculate the difference between two datetime values, where the only significant portions are the year and month.
I'll talk about these new datatypes in more detail in a future article.
Since person_ot is a subtype of living_thing_ot, when I declare a person object, I must provide a total of four values in the constructor. This is shown here:
DECLARE
steven person_ot :=
person_ot (
'HUMAN',
'Steven',
175,
'23-SEP-1958');
BEGIN
steven.weight := 170;
steven.showPoliticalPower;
END;
I provide a value for the living_thing_ot attribute, species and my three person-
specific attributes. I can then directly address any of the attributes and call my methods.
Reflections on Inheritance
The ability to inherit methods and attributes from supertypes lends much power to object types, but it also introduces a higher level of complexity and dependency. The reason for this is that inheritance isn't a one-time affair in object types.
Any changes made after the initial definition of the hierarchy are reflected in the subtype as well. Unless a subtype overrides an inherited method, it always contains the same set of attributes and methods that are in the accumulation of supertypes in the hierarchy, plus any attributes and methods that the subtype contributes.
From this perspective, it's important to keep in mind that a subtype isn't a different type from any of its supertypes. Instead, it's a more specific kind of that type. If, for example, the characteristics of the employee object-type change, then the definition of the salaried employee changes as well.
This live connection means that you can make a change deep in the hierarchy that automatically affects many object types and the tables and code built around those types. That may be just what you want, but it also means that as you change one level in the hierarchy you need to think through the answers to such questions as:
- If you're adding a new method, do you want to allow subtypes to redefine that method? Should all subtypes be required to use the method unchanged?
- If the type or its subtypes are referenced in the definition of an object-relational table, do you want it to be available through all DML operations or should access be restricted?
Extending the Hierarchy
There's no limit to the number of levels in one's object-type hierarchy. With the hierarchy described earlier in this article, for example, I'd define my objects as follows (header lines only):
CREATE TYPE living_thing_ot IS OBJECT...
CREATE TYPE person_ot UNDER living_thing_ot...
CREATE TYPE citizen_ot UNDER person_ot...
CREATE TYPE war_criminal_ot UNDER citizen_ot...
CREATE TYPE corporation_ot UNDER person_ot...
CREATE TYPE employee_ot UNDER person_ot...
CREATE TYPE salaried_emp_ot UNDER employee_ot...
CREATE TYPE hourly_emp_ot UNDER employee_ot...
CREATE TYPE manager_ot UNDER salaried_emp_ot...
CREATE TYPE admin_ot UNDER salaried_emp_ot...
CREATE TYPE professional_ot UNDER salaried_emp_ot...
At each stage of the hierarchy, you need to decide:
- Should my object type be
INSTANTIABLEorNOT INSTANTIABLE? Will this object type, in other words, be used solely as a supertype of specialized subtypes? - Should my object type be
FINALorNOT FINAL? Can this object type be used as a supertype of more specialized subtypes? Or is it the "end of the line" in the hierarchy?
And then within each object type, you should examine your different methods and
decide whether you want them to be INSTANTIABLE (which means you can override
them in a subtype) or FINAL (they can't be overridden).
If you know that you're going to override a method in every subtype because it's
defined differently at every level, there isn't any point in providing an implementation in
the supertype. So you declare the method as INSTANTIABLE and compel all subtypes to
implement the method.
The INSTANTIABLE status of an object type can be modified with the ALTER
TYPE statement. Suppose, for example, I want to change the company type from NOT
INSTANTIABLE to INSTANTIABLE. I can issue this statement:
ALTER TYPE company_ot INSTANTIABLE;
You can also change a type from INSTANTIABLE to NOT INSTANTIABLE with
the ALTER TYPE command, but only if the target type has no columns, views, tables, or
instances that reference that type, either directly, or indirectly through another type or
subtype.



