[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-