Go to the Next or Previous section, the Detailed Contents, or the Amiga E Encyclopedia.


17.5 Data-Hiding in E

Data-hiding is accomplished in E at the module level. This means, effectively, that it is wise to define classes in separate modules (or at least only closely related classes together in a module), taking care to EXPORT only the definitions that you need to. You can also use the PRIVATE keyword in the definition of any OBJECT to hide all the elements following it from code which uses the module (although this does not affect the code within the module). The PUBLIC keyword can be used in a similar way to make the elements which follow visible (i.e., accessible) again, as they are by default. For instance, the following OBJECT definition makes x, y, a and b private (so only visible to the code within the same module), and p, q and r public (so visible to code external to the module, too).

OBJECT rec
  p:INT
PRIVATE
  x:INT
  y
PUBLIC
  q
  r:PTR TO LONG
PRIVATE
  a:PTR TO LONG, b
ENDOBJECT

For the set class you would probably want to make all the data private and all the methods public. In this way you force programs which use this module to use the supplied interface, rather than fiddling with the set data structures themselves. The following example is the complete code for a simple, inefficient set class, and can be compiled to a module.

OPT MODULE  -> Define class 'set' in a module
OPT EXPORT  -> Export everything

/* The data for the class */
OBJECT set PRIVATE  -> Make all the data private
  elements:PTR TO LONG
  maxsize, size
ENDOBJECT

/* Creation constructor */
/* Minimum size of 1, maximum 100000, default 100 */
PROC create(sz=100) OF set
  DEF p:PTR TO LONG
  self.maxsize:=IF (sz>0) AND (sz<100000) THEN sz ELSE 100 -> Check size
  self.elements:=NEW p[self.maxsize]
ENDPROC

/* Copy constructor */
PROC copy(oldset:PTR TO set) OF set
  DEF i
  self.create(oldset.maxsize)  -> Call create method!
  FOR i:=0 TO oldset.size-1  -> Copy elements
    self.elements[i]:=oldset.elements[i]
  ENDFOR
  self.size:=oldset.size
ENDPROC

/* Destructor */
PROC end() OF set
  DEF p:PTR TO LONG
  IF self.maxsize<>0  -> Check that it was allocated
    p:=self.elements
    END p[self.maxsize]
  ENDIF
ENDPROC

/* Add an element */
PROC add(x) OF set
  IF self.member(x)=FALSE  -> Is it new? (Call member method!)
    IF self.size=self.maxsize
      Raise("full")  -> The set is already full
    ELSE
      self.elements[self.size]:=x
      self.size:=self.size+1
    ENDIF
  ENDIF
ENDPROC

/* Test for membership */
PROC member(x) OF set
  DEF i
  FOR i:=0 TO self.size-1
    IF self.elements[i]=x THEN RETURN TRUE
  ENDFOR
ENDPROC FALSE

/* Test for emptiness */
PROC empty() OF set IS self.size=0

/* Union (add) another set */
PROC union(other:PTR TO set) OF set
  DEF i
  FOR i:=0 TO other.size-1
    self.add(other.elements[i])  -> Call add method!
  ENDFOR
ENDPROC

/* Print out the contents */
PROC print() OF set
  DEF i
  WriteF('{ ')
  FOR i:=0 TO self.size-1
    WriteF('\d ', self.elements[i])
  ENDFOR
  WriteF('}')
ENDPROC

This class can be used in another module or program, as below:

MODULE '*set'

PROC main() HANDLE
  DEF s=NIL:PTR TO set
  NEW s.create(20)
  s.add(1)
  s.add(-13)
  s.add(91)
  s.add(42)
  s.add(-76)
  IF s.member(1) THEN WriteF('1 is a member\n')
  IF s.member(11) THEN WriteF('11 is a member\n')
  WriteF('s = ')
  s.print()
  WriteF('\n')
EXCEPT DO
  END s
  SELECT exception
  CASE "NEW"
    WriteF('Out of memory\n')
  CASE "full"
    WriteF('Set is full\n')
  ENDSELECT
ENDPROC


Go to the Next or Previous section, the Detailed Contents, or the Amiga E Encyclopedia.