Constructors
A constructor runs when an object is created, so an object can never be seen half-built. A type may have several, told apart by their parameters like overloaded procedures.
type Temperature
declare constructor( ) '' the default
declare constructor( byval celsius as float64 )
declare constructor( byref text as ustring )
celsius as float64
end type
constructor Temperature( )
celsius = 20
print " default: room temperature"
end constructor
constructor Temperature( byval celsius as float64 )
this.celsius = celsius
print " from a number"
end constructor
'' One constructor can hand its work to another.
constructor Temperature( byref text as ustring )
this.constructor( val( text ) )
print " ... by way of the text"
end constructor
sub Show( byref t as Temperature )
print " Show got"; t.celsius
end sub
print "dim as Temperature a"
dim as Temperature a
print "var b = Temperature( 5.5 )"
var b = Temperature( 5.5 )
print "dim as Temperature c = Temperature( ""31"" )"
dim as Temperature c = Temperature( "31" )
'' A constructor with one parameter is also a conversion.
print "dim as Temperature d = -4"
dim as Temperature d = -4
print "Show( 12 )"
Show( 12 )
'' An array of objects runs the default constructor for each element.
print "dim as Temperature week( 1 to 2 )"
dim as Temperature week( 1 to 2 )
print "celsius: " & a.celsius & ", " & b.celsius & ", " & c.celsius & _
", " & d.celsius
Output
dim as Temperature a
default: room temperature
var b = Temperature( 5.5 )
from a number
dim as Temperature c = Temperature( "31" )
from a number
... by way of the text
dim as Temperature d = -4
from a number
Show( 12 )
from a number
Show got 12
dim as Temperature week( 1 to 2 )
default: room temperature
default: room temperature
celsius: 20, 5.5, 31, -4
The constructor with no parameters is the default constructor. A plain
dim as Temperature a uses it, and so does every element of an array of
objects.
The others are chosen by their arguments, wherever an object is made:
| Form | Calls |
|---|---|
dim as Temperature a | the default constructor |
var b = Temperature( 5.5 ) | the float64 constructor |
dim as Temperature c = Temperature( "31" ) | the ustring constructor |
dim as Temperature d = -4 | the float64 constructor, as a conversion |
One constructor can delegate to another with this.constructor( ... ).
The text constructor converts its argument and hands the rest of the work to
the number constructor, so the setup lives in one place.
A type that declares constructors but no default one cannot be created with
a plain dim: the compiler refuses it with TKO0657: the type of 'a' has no constructor that takes no argument. Default parameter values, such as
declare constructor( byval n as int32 = 0 ), give one constructor that
serves both ways.
A constructor with one parameter is also an implicit conversion. Because
Temperature can be built from a float64, the compiler builds one on its
own whenever a number appears where a Temperature is wanted: that is what
dim as Temperature d = -4 and Show( 12 ) did. There is no keyword to turn
this off (declare explicit constructor is refused with TKO0936). If a
silent conversion would be wrong for your type, give the constructor a second
parameter, or create objects through a named function.
Activities
- Add a constructor that takes a temperature in Fahrenheit. What has to be different about its parameter list so the compiler can tell it from the Celsius one?
- Remove the default constructor and read the error for
dim as Temperature a. Then give thefloat64parameter a default value and try again.