Access control
A type that keeps rules about its data, such as "a balance never goes negative", can only keep them if nothing else can write that data. Access sections let a type decide which of its members the rest of the program may touch.
type Account
public: '' anyone may use these
declare constructor( byval opening as int64 )
declare sub Deposit( byval amount as int64 )
declare function Withdraw( byval amount as int64 ) as boolean
declare function Balance( ) as int64
private: '' only Account's own methods
declare sub Record( byref what as ustring )
balance_ as int64
entries_ as int32
end type
constructor Account( byval opening as int64 )
balance_ = iif( opening < 0, 0, opening )
Record( "opened" )
end constructor
sub Account.Deposit( byval amount as int64 )
if amount <= 0 then exit sub '' the type keeps its own rules
balance_ += amount
Record( "deposit" )
end sub
function Account.Withdraw( byval amount as int64 ) as boolean
if amount <= 0 orelse amount > balance_ then return false
balance_ -= amount
Record( "withdrawal" )
return true
end function
function Account.Balance( ) as int64
return balance_
end function
'' A private method is a helper the outside world never sees.
sub Account.Record( byref what as ustring )
entries_ += 1
print " entry"; entries_; ": "; what
end sub
dim as Account acct = Account( 100 )
acct.Deposit( 50 )
acct.Deposit( -1000 ) '' ignored
var tooMuch = acct.Withdraw( 500 )
var enough = acct.Withdraw( 30 )
print "withdraw 500: "; tooMuch; ", withdraw 30: "; enough
print "balance:"; acct.Balance( )
Output
entry 1: opened
entry 2: deposit
entry 3: withdrawal
withdraw 500: false, withdraw 30: true
balance: 120
Inside a type, a label starts a section that runs to the next label:
| Label | Members reachable from |
|---|---|
public: | anywhere; this is the default before any label |
private: | the type's own methods, constructors and operators only |
protected: | the type's own methods and those of types derived from it |
The private section of Account holds the balance, an entry counter and
Record, a helper method. Every change to the balance goes through
Deposit or Withdraw, which refuse what the account does not allow, so the
balance cannot go wrong from outside. Reaching for the field directly is a
compile error:
type Account
declare function Balance( ) as int64
private:
balance_ as int64
end type
function Account.Balance( ) as int64
return balance_
end function
dim as Account acct
acct.balance_ = 1000000 '' refused: balance_ is private
accesserror.tiko(12,5): error TKO0625: 'balance_' is not accessible here
|
12 | acct.balance_ = 1000000 '' refused: balance_ is private
| ^
A global operator, such as an operator = written for the type, is not a
method, so it sees only the public members too; build it from the type's
public methods. protected: matters once types extend one another, in
Inheritance.
The trailing underscore on balance_ is a naming habit, not syntax. It marks
the data the methods look after and leaves the plain name free for a method
or property that exposes it.
A type with a private constructor and a public static function that
creates it is the usual way to insist that objects are made only through
that function. In this version var acct = Account.Open( 100 ) is refused
with TKO0633 as soon as the type has any private constructor, so that
pattern cannot be used yet.
Activities
- Add a public
Entries( )function that returns how many entriesRecordhas made. - Move
Depositinto the private section and read the error foracct.Deposit( 50 ).