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

[REBOL] Re: Is Rebol OO?

From: joel:neely:fedex at: 12-Jan-2004 7:42

Hi, Behrang, Behrang Saeedzadeh wrote:
> ... is REBOL Object Oriented? >
As you can tell from the variety of responses, the question is a bit tricky to handle. Unfortunately, the phrase "object oriented" has been siezed on by marketers, reporters, comp sci researchers, methodologists, consultants, and snake oil salesmen, and given different spins by all of the above. Let me duck the phrasing of your original question, and answer a closely-related one, in the hope that something I say will address your needs: I already know how to program in language XYZ, which is commonly regarded as an object-oriented language. How much of what I know about programming in XYZ will be useful to programming in REBOL? Answering this modified question would require addressing some of the following issues: 1) REBOL is a dynamically-typed language. This is familiar territory if you are used to Smalltalk, Python, or Perl; It may take some adjustment if you are used to Java, C++, Eiffel, Delphi, etc. Type errors (attempting to apply an innappropriate operation on a value, trying to access a non-existent component of an object, etc.) are caught at run time, not prevented at compile time. 2) An object in REBOL is a namespace. The values associated with the words defined in an object represent the state of the object, and functions defined (at creation time) within the object use those words in the familiar way: sample: make object! [ some-data: "Hello, world!" some-method: func [] [print some-data] ] Immediately after evaluating the above definition, an evaluation of SOME-METHOD results in the output of Hello, world! regardless of whether there's a word SOME-DATA defined anywhere else (e.g. globally, within another object, etc.) 3) All words defined within an object are "public". That's why I had to say "immediately after evaluating..." in the previous point. Given the above object, you can also say sample/some-data: "Goodbye, cruel world!" to change the state of SAMPLE. There's no built-in way to make SOME-DATA private, and inaccessible to the rest of the world. 4) REBOL uses a prototype model of object creation, rather than a class-based model or a delegation model. Objects are made one-at-a-time and one-of-a-kind. You can use a block (as in the above example) as a specification for creating an object, and can use the same block repeatedly: sample-spec: [ some-data: "Hello, world!" some-method: func [] [print some-data] ] sample1: make object! sample-spec sample2: make object! sample-spec sample3: make object! sample-spec but once those objects are created, each has a life (state) of its own; any resemblance is viewed by REBOL as merely coincidental. In particular, each of the above objects has its *own* function named SOME-METHOD . There's no concept in REBOL of "instance method" shared between the objects. You can also use an existing object as a specification: demo1: make object! [ some-data: "Hello, world!" some-method: func [] [print some-data] ] demo2: make demo1 [] demo3: make demo2 [] but, again, a newly created object is like a newly-hatched sea turtle; it resembles any siblings which may have come from the same parent, but immediatly upon hatching, it must face the wild ocean on its own. It has no parent. 5) As a consequence of all of the above (and the dynamic nature of REBOL itself) you can build your own convenience methods to implement some features you may be accustomed to using: greeter-class: make object! [ _greeter: make object! [ greetee: "TBD" greet: func [] [greeter-class/_greet self] ] new: func [who [string!]] [ make _greeter [greetee: copy who] ] _greet: func [which [object!]] [ print ["Hello," which/greetee] ] ] which provides a constructor (NEW) and a single shared method for all "instances" (GREETER-CLASS/GREET), which defer to the "class" definition...
>> world-greeter: greeter-class/new "world!" >> mom-greeter: greeter-class/new "Mom!" >> lonesome-greeter: greeter-class/new "anybody?"
...so that each "instance" uses the common behavior:
>> world-greeter/greet
Hello, world!
>> mom-greeter/greet
Hello, Mom!
>> lonesome-greeter/greet
Hello, anybody? Of course this is overkill for something as simple as shown above, but if the GREET method were complex and lengthy, it would save space to have each "instance" object contain only "stub" methods that dispatch themselves to a common function. (There's nothing magic about the underscores; I just used underscore prefixes to remind myself that some parts of GREETER-CLASS are not intended for general use. There's no mechanism in REBOL that enforces that idea.) Perhaps this gives you some sense of what you can do with objects in REBOL, but of course there's always more... Hope this helps! -jn-