comp.lang.ada
 help / color / mirror / Atom feed
From: "Lucretia" <lucretia9@lycos.co.uk>
Subject: Ada 2005: Attempting to create a useful subject/observer pattern
Date: 24 Oct 2006 14:01:50 -0700
Date: 2006-10-24T14:01:50-07:00	[thread overview]
Message-ID: <1161723710.859323.228560@f16g2000cwb.googlegroups.com> (raw)

Hi,

Like the subject states, I'm trying to implement a usable
subject/observer pattern which is an extension of the GoF original and
something closer to Java's Listeners. The idea was to use the code in a
gui library. After talking on IRC (#Ada) and working with the guys
there (Baldrick ;D), it was noted that GNAT is flawed in it's
interfaces, but I'd like to know if anyone here can indicate whether
the code is wrong and GNAT should accept it or not.

I'm using FSF GNAT from GCC 4.1.1 and the errors are:

gnatmake -gnat05 test_observers2.adb
gcc -c -gnat05 test_observers2.adb
test_observers2.adb:16:34: (Ada 2005) interface subprogram "Update"
must be abstract or null
test_observers2.adb:23:31: expected private type "Event" defined at
events.ads:5test_observers2.adb:23:31: found private type "Mouse_Event"
defined at mouse_events.ads:5
my_observer.ads:10:03: (Ada 2005) interface subprogram "On_Mouse_Click"
must be abstract or null
subjects.ads:15:10: (Ada 2005) interface subprogram "Update" must be
abstract or null
subjects.ads:15:20: operation can be dispatching in only one type
gnatmake: "test_observers2.adb" compilation error

Thanks,
Luke.

All code below is GPL'd and can be gnatchopped:

with Ada.Finalization;

package Events is

  type Event is new Ada.Finalization.Controlled with private;

private

  type Event is new Ada.Finalization.Controlled with null record;

end Events;
with Events;

package Mouse_Events is

  type Mouse_Event is new Events.Event with private;

private

  type Mouse_Event is new Events.Event with null record;

end Mouse_Events;
with Mouse_Events;
with Observers;

package Mouse_Observers is

  type Mouse_Observer is interface and Observers.Observer;

  procedure On_Mouse_Click(Self : in Mouse_Observer; Event : in
Mouse_Events.Mouse_Event) is null;

end Mouse_Observers;
with Ada.TexT_IO;

package body My_Observer is

--  procedure Update(Self : in My_Observer_Type) is

--  begin

--    Ada.TexT_IO.Put_Line("[My_Observer.Update]");

--  end Update;

  procedure On_Mouse_Click(Self : in Mouse_Observer; Event : in
Mouse_Events.Mouse_Event) is

  begin

    Ada.TexT_IO.Put_Line("[My_Observer.On_Mouse_Click]");

  end On_Mouse_Click;

end My_Observer;
with Mouse_Observers;
with Mouse_Events;

package My_Observer is

  type My_Observer_Type is new Mouse_Observers.Mouse_Observer with
private;

  overriding
--  procedure Update(Self : in My_Observer_Type);
  procedure On_Mouse_Click(Self : in Mouse_Observers.Mouse_Observer;
Event : in Mouse_Events.Mouse_Event);

private

  type My_Observer_Type is new Mouse_Observers.Mouse_Observer with null
record;

end My_Observer;
package Observers is

  type Observer is interface;
  type Observer_Access is access all Observer'Class;

end Observers;
with Observers;

package body Subjects is

  use type Observer_Lists.Cursor;

  -- Add an observer to this subject's internal list.
  procedure Attach(Self : in out Subject'Class; Observer : access
Observers.Observer'Class) is

  begin

    Self.Observer_List.Append(New_Item =>
Observers.Observer_Access(Observer));

  end Attach;


  -- Remove an observer from this subject's internal list.
  procedure Detach(Self : in out Subject'Class; Observer : access
Observers.Observer'Class) is

    Position : Observer_Lists.Cursor :=
Self.Observer_List.Find(Observers.Observer_Access(Observer));

  begin

    if Position /= Observer_Lists.No_Element then

      Self.Observer_List.Delete(Position);

    end if;

  end Detach;


  -- Notify all observers who are monitoring this subject that
something has happened.
  procedure Notify(Self : in Subject; Event : in Events.Event) is

    Current : Observer_Lists.Cursor := Self.Observer_List.First;

  begin

    while Current /= Observer_Lists.No_Element loop

      if Observer_Lists.Element(Current)'Class = Matching_Event'Class
then

        Update(Observer_Lists.Element(Current), Event);

        --Observer_Lists.Element(Current).Update;

        Current := Observer_Lists.Next(Current);

      end if;

    end loop;

  end Notify;


--  function Equals(Left, Right : access Observers.Observer) return
Boolean is
  function Equals(Left, Right : Observers.Observer_Access) return
Boolean is

    use type Observers.Observer_Access;

  begin

    if Left = Right then

      return True;

    end if;

    return False;

  end Equals;

end Subjects;
with Observers;
with Ada.Containers.Doubly_Linked_Lists;
with Ada.Finalization;
with Events;

package Subjects is

  type Subject is new Ada.Finalization.Limited_Controlled with private;

  procedure Attach(Self : in out Subject'Class; Observer : access
Observers.Observer'Class);
  procedure Detach(Self : in out Subject'Class; Observer : access
Observers.Observer'Class);

  generic
    type Matching_Event is new Events.Event with private;
    with procedure Update(Self : in Observers.Observer; Event : in
Events.Event) is abstract;
  procedure Notify(Self : in Subject; Event : in Events.Event);

private

  function Equals(Left, Right : Observers.Observer_Access) return
Boolean;

  package Observer_Lists is new
Ada.Containers.Doubly_Linked_Lists(Observers.Observer_Access, Equals);

  type Subject is new Ada.Finalization.Limited_Controlled with
    record
      Observer_List : Observer_Lists.List;
    end record;

end Subjects;
with My_Observer;
with Subjects;
--with Observers;
with Mouse_Events;

procedure Test_Observers2 is

--  Obs     : Observers.Observer_Access := new
My_Observer.My_Observer_Type;
--  Obs     : access Observers.Observer := new
My_Observer.My_Observer_Type;
  Obs         : aliased My_Observer.My_Observer_Type;
  Subject     : Subjects.Subject;
  Mouse_Event : Mouse_Events.Mouse_Event;

  procedure Notify_Mouse_Click is new Subjects.Notify(
    Matching_Event => Mouse_Events.Mouse_Event,
    Update         => My_Observer.On_Mouse_Click);

begin

  Subject.Attach(Obs'Access);
--  Subject.Attach(Observers.Observer(Obs)'Access);
--  Subject.Notify;
  Notify_Mouse_Click(Subject, Mouse_Event);
  
end Test_Observers2;




             reply	other threads:[~2006-10-24 21:01 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-10-24 21:01 Lucretia [this message]
2006-10-24 21:08 ` Ada 2005: Attempting to create a useful subject/observer pattern Lucretia
2006-10-25  2:01 ` Adam Beneschan
2006-10-25  8:22 ` Dmitry A. Kazakov
2006-10-25 16:29 ` Matthew Heaney
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox