The objects are naturally extensible, meaning that the attributes and methods of one object can be made available to one or more objects. This property is called as inheritance. The object which inherits the behavior of other objects is called as a Subtype and the object which is being inherited is called as the Supertype.
When you create an instance for the subtype, the instance inherits the behavior of both the supertype and the subtype. A subtype cannot inherit the properties of two supertypes when there is no relationship between them, similar to how a human child cannot have more than one father or one mother. But the subtype created on a supertype can inherit the properties of that supertype and all its parent supertypes if present.
A method in a supertype is by default overridden when the subtype provides a method with the same name and type, similar to its supertype. This default behavior can be changed by using the generalized invocation as shown below,
Consider a method print is available in both the supertype and its subtype,
(Instance_name as supertype).print invocation will call the print method from the supertype.
(Instance_name as subtype).print invocation will call the print method from the subtype.
In the below snippet, a supertype OBJ_SUPERTYPE is created with two attributes, one map member function comparing the employee ID and a member function for returning the name of the employee for a particular ID. This supertype is defined as NOT Final, thus this object can be inherited by any other types.
CREATE OR REPLACE type obj_supertype IS object
(obj_emp_id VARCHAR2(30),
obj_emp_name VARCHAR2(30),
map member FUNCTION func_super_map RETURN NUMBER,
member FUNCTION func_super_print RETURN VARCHAR2)
NOT final;
/
CREATE OR REPLACE type body obj_supertype
IS
map member FUNCTION func_super_map RETURN NUMBER
IS BEGIN
RETURN obj_emp_id;
END;
member FUNCTION func_super_print RETURN VARCHAR2
IS BEGIN
RETURN 'The Employee details for the ID '||obj_emp_id||' is Name: '|| obj_emp_name;
END;
END;
/
In the below listing, an instance for the object type OBJ_SUPERTYPE is created with user defined initialization values in the declaration section. The execution section of the block makes a call to the member function and its return value is printed using the PUT_LINE procedure.
DECLARE
l_obj_supertype obj_supertype := obj_supertype(857, 'Thomas King'); --type constructor has been used here
BEGIN
dbms_output.put_line(l_obj_supertype.func_super_print);
END;
/
Result: The Employee details for the ID 857 is Name: Thomas King
A subtype has been created under the above supertype with two new attributes pertaining to it along with a member function having the same name as that of the super type’s member function. In the body section, the member function calls the supertype’s member function by prefixing the function name with the generalized invocation parameter, Self AS obj_supertype, and concatenating its return value with its own attribute’s values. The obtained result set acts as the return value for the member function.
CREATE OR REPLACE type obj_subtype under obj_supertype
(obj_emp_job VARCHAR2(30),
obj_emp_sal NUMBER,
overriding member FUNCTION func_super_printRETURN VARCHAR2);
/
CREATE OR REPLACE type body obj_subtype
AS
overriding member FUNCTION func_super_print
RETURN VARCHAR2
IS
BEGIN
RETURN (self AS obj_supertype).func_super_print||', Job ID: '||obj_emp_job||', Salary: '||obj_emp_sal||'$';
END;
END;
/
The below anonymous block creates an instance of the subtype and initializes it with the user defined values. Here, the first two attributes in the constructor function initialization are overridden from the supertype and the next two attributes are its own.
In the execution section, the first PUT_LINE procedure calls the member function from the supertype using the generalized invocation parameter, (l_obj_subtype AS obj_supertype).func_super_print and thesecond PUT_LINE procedure makes its call to the member function from the subtype using the generalized invocation parameter, (l_obj_subtype AS obj_subtype).func_super_print, both the invocations are performed on the subtype’s instance variable l_obj_subtype.
DECLARE
l_obj_subtype obj_subtype:=obj_subtype(857, 'Thomas King', 'Assistant Manager', 3500);
BEGIN
dbms_output.put_line((l_obj_subtype AS obj_supertype).func_super_print);
dbms_output.put_line((l_obj_subtype AS obj_subtype).func_super_print);
END;
/
Result:
The Employee details for the ID 857 is Name: Thomas King
The Employee details for the ID 857 is Name: Thomas King, Job ID: Assistant Manager, Salary: 3500$
In the below snippet, the subtype is initialized with the four attributes of user-defined values.The execution section makes its first PUT_LINE procedure to call the member function of the supertype with the subtype’s instance variable as its argument, returning the RETURN value of the supertype’s member function. As the supertype has only access to the first two attributes of the subtype, the first PUT_LINE procedure returns only the values of the first two attributes from the initialization variable.
The second PUT_LINE procedure makes the call to the supertype’s member function similar to its previous statement, but this time, a general invocation parameter, (l_obj_subtype AS obj_subtype) is passed as its argument, returning the complete initialization variable values. Here, the supertype’s member function has overridden the subtype’s member function, which is an uncommon behavior.
DECLARE
l_obj_subtype obj_subtype:=obj_subtype(857, 'Thomas King', 'Assistant Manager', 3500);
BEGIN
dbms_output.put_line(obj_supertype.func_super_print(l_obj_subtype));
dbms_output.put_line(obj_supertype.func_super_print((l_obj_subtype AS obj_subtype)));
END;
/
Result:
The Employee details for the ID 857 is Name: Thomas King
The Employee details for the ID 857 is Name: Thomas King, Job ID: Assistant Manager, Salary: 3500$
Restrictions in inheriting a Supertype:
1. When an object is created as Final, which is the default when not explicitly mentioned, means that no subtypes can be derived from it. NOT Final means that subtypes can be derived.
2. When a method is created as Final, means that subtypes cannot override it by providing their own implementation. NOT Final, which is the default if not explicitly mentioned, means that the supertype method can be overridden.
3. The attributes in the supertype cannot be overridden, meaning that the same name cannot be used for the attributes in the supertype and the subtype.
4. Only one MAP or one ORDER function may be implemented in a type hierarchy of supertypes and subtypes.
5. In a type hierarchy, if the supertype does not specify a MAP or an ORDER function, neither can its subtypes.
6. Only the MAP function can be overridden and not the ORDER function.
7. A static method and a member method in a subtype may not redefine a member method and a static method in the supertype respectively.
8. If an overridden method has default values for any of its parameters, then the overriding method must provide the same default values for the same parameters.