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
- Add a
Trianglewith a base and a height, and put one in the array. Which existing lines did you have to change? - Leave
Nameout ofTriangleand read the error.