Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search

[REBOL] Re: Rebol Framework suggestion

From: doublec:acc at: 11-Sep-2001 14:17

> Usually in OOP, the Class defines the methods and properties of an > object and the objects will implements their own properties based on > the class...
Not always. What you define above is class based OOP. There is also generic function based oop as used by languages like Common Lisp and Dylan. Warning, longish discussion on differences between the different ways of doing OOP below. In generic function based OOP the methods do not belong to a class. All arguments passed to a method are used in resolving what method to call. This is known as multiple dispatch. It's similar to C++ overloading, but determined by run time types rather than compile time types. So for example, in C++: class Window {}; class Event {}; class ApplicationWindow1 : public Window {}; class LeftClickEvent : public Event {}; void HandleEvent(Window* window, Event* event); void HandleEvent(ApplicationWindow1* window, LeftClickEvent* event); Event* event = new LeftClickEvent; Window* window = new ApplicationWindow1; HandleEvent(window, event); This calls HandleEvent(Window*, Event*) rather than HandleEvent(ApplicationWindow1*,LeftClickEvent*) as you might want. This is because the dispatch is based on the compile time type of the arguments. Now you could make HandleEvent a virtual function to get run time dispatch. But then the dispatch occurs only on the first argument, the Window type. How to also dispatch on the second argument? For example, in C++ with virtual functions: class Event {}; class LeftClickEvent : public Event {}; class Window { public: virtual void HandleEvent(Event* event); virtual void HandleEvent(LeftClickEvent* event); }; class ApplicationWindow1 : public Window { public: virtual void HandleEvent(Event* event); virtual void HandleEvent(LeftClickEvent* event); }; Event* event = new LeftClickEvent; Window* window = new ApplicationWindow1; window->HandleEvent(event); Again, you might expect HandleEvent(LeftClickEvent*) of the ApplicationWindow1 class to be called but this does not happen. Instead HandleEvent(Event*) of the ApplicationWindow1 class is called. Why? Because the static type of the second argument is an Event*. The run time type is a LeftClickEvent*. Method dispatch on arguments for C++ methods are for the static type. The other problem occurs with every Window class needing to know about every Event class. When a new Event class is created you must go back and modify every existing Window class to add a handler for it. Note that Java and Smalltalk have similar problems as C++ here. This is the main reason for the existance of the Visitor pattern - workarounds for the lack of multi method dispatch. A generic function based OOP system dispatches all arguments on the run time type of the arguments, and allow extending the methods of a class without having to go back and re-edit the class. This is because methods do not 'belong' to a class. They belong to 'generic functions' which contain collections of methods. When a generic function is called all the methods that belong to that generic are examined and the method that takes the most specific arguments that are passed is called. So in Dylan, the following example works as expected: define class <window> (<object>) end; define class <application-window1> (<window>) end; define class <event> (<object>) end; define class <left-click-event> (<event>) end; define generic handle-event(window :: <window>, event :: <event>); // Methods look stand-alone but they are implicitly belong to the generic // function of the same name. define method handle-event(window :: <application-window1>, event :: <left-click-event>) // do something end; define method handle-event(window :: <window>, event :: <event>) // do something else end; let event :: <event> = make(<left-click-event>); let window :: <window> = make(<application-window1>); handle-event(window, event); Here the handle-event method called is the one that has the <application-window1> and <left-click-event> arguments. Or any other method that fits into the inheritance hierarchy. I believe this form of OO, as used by Dylan and CLOS, is easier to use than the C++/Java form of class based OO. Extension without modifying existing classes is easier, and multi-method dispatch is something you wonder how you managed to live without when you get used to it. Another language that uses multi-method dispatch is Cecil , and I'm sure there are others. If you are thinking of implementing OO ideas on top of Rebol, you might like to consider some of the alternative OO systems. Here's some links: Dylan: Cecil: Common Lisp (CLOS): Please note that I include these links and the examples above not as advertisements for using other languages. I include them so you can get a feel for how different OO systems exist, possibly easier to use than standard class based OO, and how you might like to include some of the ideas in Rebol if you are looking to create an OO system for Rebol. Chris.