Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Abstract methods

Some base types cannot say how to do something, only that every derived type can. A Shape has no area of its own, yet every shape has one. An abstract method is a virtual method with no body: the base declares it, and each derived type must supply it.

'' Shape says every shape has an area and a name, without saying how.
type Shape extends Object
    declare abstract function Area( ) as float64
    declare abstract function Name( ) as ustring
    declare function Describe( ) as ustring
end type

function Shape.Describe( ) as ustring
    return Name( ) & " with area " & Area( )
end function

type Rect extends Shape
    declare constructor( byval w as float64, byval h as float64 )
    declare function Area( ) as float64 override
    declare function Name( ) as ustring override
    w as float64
    h as float64
end type

constructor Rect( byval w as float64, byval h as float64 )
    this.w = w : this.h = h
end constructor

function Rect.Area( ) as float64
    return w * h
end function

function Rect.Name( ) as ustring
    return "a " & w & " by " & h & " rectangle"
end function

type Circle extends Shape
    declare constructor( byval r as float64 )
    declare function Area( ) as float64 override
    declare function Name( ) as ustring override
    r as float64
end type

constructor Circle( byval r as float64 )
    this.r = r
end constructor

function Circle.Area( ) as float64
    return 3.14159 * r * r
end function

function Circle.Name( ) as ustring
    return "a circle of radius " & r
end function

dim as Rect door = Rect( 1, 2 )
dim as Circle coin = Circle( 2 )
dim as Shape ptr shapes( 0 to 1 ) = { @door, @coin }

dim as float64 total = 0
for i as int32 = 0 to 1
    print shapes( i )->Describe( )
    total += shapes( i )->Area( )
next
print "total area:"; total

Output

a 1 by 2 rectangle with area 2
a circle of radius 2 with area 12.56636
total area: 14.56636

declare abstract function Area( ) as float64 declares the method and nothing else; there is no Shape.Area body anywhere. Rect and Circle each supply both abstract methods with override, and Shape.Describe, written once in the base, calls whichever versions the object really has.

A type with an abstract method is incomplete on purpose, so no object of it can exist; there would be nothing to run if someone asked for its area:

type Shape extends Object
    declare abstract function Area( ) as float64
end type

dim as Shape s                      '' refused: Area has no body
print s.Area( )
abstracterror.tiko(5,14): error TKO0620: 's' has an abstract type, which cannot be instantiated
     |
   5 | dim as Shape s                      '' refused: Area has no body
     |              ^

A derived type that leaves any abstract method unwritten is abstract too, and refused with the same error. What can exist is a Shape ptr, or a byref parameter of type Shape, referring to an object of a complete type, as the shapes array does.

Like virtual, abstract needs a type that extends Object: on any other type it is refused with TKO0645: 'area' is virtual, but its type does not extend 'object'.

Activities

  1. Add a Triangle with a base and a height, and put one in the array. Which existing lines did you have to change?
  2. Leave Name out of Triangle and read the error.