IMPLEMENTATION MODULE AbstractClasses;

  CLASS AbstractChar;
    VAR
      Value: CHAR;
      
    METHOD Set(Ch: CHAR);
      BEGIN
      Value := Ch;
      END Set;
      
    METHOD Get: CHAR;
      BEGIN
      RESULT := Value;
      END Get;
      
  END AbstractChar;
--------------------------------------------
  CLASS AbstractInteger;
    VAR
      Value: INTEGER;
      
    METHOD Set(Int: INTEGER);
      BEGIN
      Value := Int;
      END Set;
      
    METHOD Get: INTEGER;
      BEGIN
      RESULT := Value;
      END Get;
      
  END AbstractInteger;
--------------------------------------------
  CLASS AbstractBoolean;
    VAR
      Value: BOOLEAN;
      
    METHOD Set(Flag: BOOLEAN);
      BEGIN
      Value := Flag;
      END Set;
      
    METHOD Get: BOOLEAN;
      BEGIN
      RESULT := Value;
      END Get;
      
  END AbstractBoolean;
--------------------------------------------
  CLASS AbstractReal;
    VAR
      Value: REAL;
      
    METHOD Set(r: REAL);
      BEGIN
      Value := r;
      END Set;
      
    METHOD Get: REAL;
      BEGIN
      RESULT := Value;
      END Get;
      
  END AbstractReal;
--------------------------------------------
  CLASS AbstractArray(Element);
    VAR
      Arr: ARRAY OF Element;
  
    REDEFINE METHOD CREATE (Size: INTEGER);
      BEGIN
      ASSERT Size >= 0;
      Arr.CREATE (Size);
      END CREATE;
      
    METHOD Get(ElNr: INTEGER): Element;
      BEGIN
      RESULT := Arr[ElNr];
      END Get;
      
    METHOD Set(ElNr: INTEGER;
               El: Element);
      BEGIN
      Arr[ElNr] := El;
      END Set;
      
    METHOD Size: INTEGER;
      BEGIN
      RESULT := Arr.SIZE;
      END Size;
      
    METHOD Slice(From, To: INTEGER): AbstractArray(Element);
      BEGIN
      RESULT.CREATE (1);
      RESULT.Arr := Arr.SLICE (From, To);
      END Slice;
      
    REDEFINE METHOD CLONE(Other: AbstractArray(Element));
      BEGIN
      Arr := Other.Arr.CLONE;
      END CLONE;
      
  END AbstractArray;
--------------------------------------------
  CLASS AbstractString;
    INHERITS AbstractArray(AbstractChar);
    
    REDEFINE METHOD CREATE(Value: ARRAY OF CHAR);
      VAR
        Ch: AbstractChar;
      BEGIN
      BASE (Value.SIZE);
      FOR i := 0 TO Value.SIZE - 1 DO
        Ch.CREATE;
        Ch.Set(Value[i]);
        Set(i, Ch);
        END;
      END CREATE;
      
  END AbstractString;                  
  
END AbstractClasses;
