Statement FINAL | INTRODUCE | OVERRIDE Foundation

Control overriding and hiding of method in subclasses or superclasses

Syntax
[FINAL | INTRODUCE | OVERRIDE] [CLASS] METHOD <MethodName>
Parameters
FINAL
The attribute FINAL declares a method to be non overridable. A FINAL method is not overriden by subclasses. Methods added to subclasses with the same name as the FINAL method hide the final method but do not change behaviour of superclasses.
INTRODUCE
The attribute INTRODUCE declares a method to hide methods of superclasses. Hiding superclass implementations does not change behaviour of superclasses. Methods of superclass calling <MethodName> still execute the superclass implementation.
OVERRIDE
The OVERRIDE attribute declares a method to override methods of superclasses. With overriding, behaviour of superclasses can be changed. Methods in superclasses calling <Methodname> will execute the subclass implementation.
<MethodName>
<MethodName> is the identifier for the method to be declared.
Description

By default all methods in Xbase++ are virtual override. This leads to the effect that a method implemented by derived classes overrides the implementation of its superclass. To control overriding and hiding of methods in your class design the attributes FINAL, INTRODUCE and OVERRIDE can be used. The following code illustrates the default behavior of Xbase++, executing the method :Bark() on a object of class A() prints "(A) says:...", while executing the method :Bark() on a object of class B() prints "(B) says:...".

CLASS A 
EXPORTED: 
INLINE METHOD Print(cText) 
  ? "(A) says:",cText 
RETURN 
INLINE METHOD Bark() 
  ::Print( "(A) is barking" ) 
RETURN 
ENDCLASS 

CLASS B FROM A 
EXPORTED: 
INLINE METHOD Print(cText) 
  ? "(B) says:",cText 
RETURN 
ENDCLASS 

Using FINAL ensures that subclasses do not override method implementations of superclasses by simply adding a method with the same name to a subclass. By adding the FINAL modifier to the Print() method declaration at class A(), the execution of the method :Bark() on a object of class B() still prints "(A) says:...". This shows the FINAL declared method Print() from class A() has been executed and not the Print() method from class B()

With INTRODUCE a new method implementation does not override method implementations of its superclasses. By adding INTRODUCE as an attribute to the Print() method at class B(), the execution of Method Bark() on objects of class B() executes method Print() at class A().

Using INTRODUCE at a subclass has the same effect as using FINAL at a superclass.

Adding OVERRIDE to a method declaration, override behaviour is enforced, even if methods at superclasses are explicitly attributed as FINAL. Assuming the method Print() at class A() is attribute as FINAL, executing method Bark() on objects of class B() leads to the execution of the Print() method at class A(). Adding OVERRIDE as an explicit attribute to the method declaration of Print() at B() leads to the execution of this new method Print() at class B() when executing the method Bark() on objects of class B().

The FINAL modifier cannot be used in conjunction with DEFERRED.

Examples
FINAL attribute for methods
// A class for managing part lists is programmed in this example. 
// The FINAL methods make sure that the calculation of total cost 
// and average cost is always done in the same way. 

CLASS PartList 
PROTECTED: 
   VAR aParts, aPrice 
EXPORTED: 
   METHOD init, add 

   FINAL METHOD totalCost, averageCost 
ENDCLASS 

METHOD PartList:init 
   ::aParts := {} 
   ::aPrice := {} 
RETURN self 

METHOD PartList:add( cPart, nPrice ) 
   AAdd( ::aParts, cPart ) 
   AAdd( ::aPrice, nPrice ) 
RETURN self 

// Calculation of total costs 
METHOD PartList:totalCost 
   LOCAL nCost := 0 
   AEval( ::aPrice, {|n| nCost += n } ) 
RETURN nCost 

// Calculation of average costs 
METHOD PartList:averageCost 
   LOCAL nCost := ::totalCost() 
   IF ! Empty( ::aParts ) 
      nCost /= Len( ::aParts ) 
   ENDIF 
RETURN nCost 

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.