{
  ex3.s

  Contents:

     1. a reflective(shell, extension) class A
     2. an extension class B whose allowed set contains A
     3. a shell class C whose allowed set contains A

  Tests:
     1. the simultaneous use of a shell and extension on the same class;
     2. message sends to "object" in shell and extension classes.

  }

reflective(shell, extension) class A
  public:
    proc m1()
      begin
      write(1);
      end
    proc m2()
      begin
      write(2);
      end
    proc m3()
      begin
      write(3);
      end
endclass

extension class B(A)
  public:
    proc m2()
      begin
      object.m2();
      write(200);
      end
endclass


shell class C(A)
  public:
    proc m1()
      begin
      object.m1();
      write(100);
      end
endclass




class Program
  public:
    proc run()
        var a : A;
      begin
      a = A.new();

      a.m1();
      a.m2();
      a.m3();

      if Reflect.attachExtension(A, B) == 0 then endif

      a.m1();
      a.m2();   // B::m2
      a.m3();

      if Reflect.attachShell(a, C.new()) == 0 then endif

      a.m1();  // C::m1
      a.m2();  // B::m2
      a.m3();

      if Reflect.removeShell(a) == 0 then endif

      a.m1();  // A::m1
      a.m2();  // B::m2
      a.m3();

      if Reflect.removeExtension(A) == 0 then endif

      a.m1();  // A::m1
      a.m2();  // A::m2
      a.m3();  // A::m3

      if Reflect.attachShell(a, C.new()) == 0 then endif

      a.m1();  // C::m1
      a.m2();  // A::m2
      a.m3();  // A::m3

      if Reflect.attachExtension(A, B) == 0 then endif

      a.m1();  // C::m1
      a.m2();  // B::m2
      a.m3();  // A::m3

      if Reflect.removeShell(a) == 0 then endif

      a.m1();  // A::m1
      a.m2();  // B::m2
      a.m3();  // A::m3

      if Reflect.removeExtension(A) == 0 then endif

      a.m1();  // A::m1
      a.m2();  // A::m2
      a.m3();  // A::m3

      end

endclass



