pseudo-class inheritance at a price ?
[1/7] from: phil:hayes:cnutarch at: 7-Oct-2001 14:25
Chris,
What about this scenario....
How would you transmit an object over an IP connection and be able to type
it?
i.e.
parent class A -> child class B
parent class A -> child class C
C: class-C-object-instance
clientfd: open tcp://localhost:9999
insert clientfd C( ? ) <- or perhaps use a refinement C/insert clientfd
close clientfd
serverfd: open tcp://:9999
listen: first serverfd
wait listen
obj: copy first listen <- or perhaps use a refinement obj/copy listen
clsoe first listen
close serverfd
No answers here but something that would definitely entyice me to use the
class methods!
[2/7] from: chrismorency:videotron:ca at: 7-Oct-2001 23:14
Hi Phil,
> What about this scenario....
> How would you transmit an object over an IP connection and be able to type
<<quoted lines omitted: 14>>
> No answers here but something that would definitely entyice me to use the
> class methods!
Hmm, I have to admit that I haven't been thinking about object over ip
connection. However, since class are still object! and object-instance are
object! too (in the rebol sense), I would expect to serve both class and
object through a connection...
Best,
Chris
[3/7] from: chrismorency:videotron:ca at: 7-Oct-2001 23:14
Hi Christian,
> some months ago I worked an a similiar project, you can find my
> code at the bottom of this mail. It's not very complete, but it
> may inspire you in a way or two :)
Thanks very much for the code, I will certainly look at it. However, my
implantation is almost complete...
> I don't believe this to be a big problem. There are other
> dialects in REBOL differing from "native" REBOL style and
> syntax, e.g. the dialects used for PARSE and VID.
Agreed.
> > 1. new class would be define like this :
> > make-class 'class-name [ ... ]
<<quoted lines omitted: 5>>
> Having a special functions for deriving classes eases reading code a lot,
> allowing for having 'class and 'superclass on the same line of code:
<code snip>
> What do you think?
Actually I had implemented the construct with and without refinements, but
thought it might be easier for developers to use the refinements... I
personnally prefer without. I'll change that ;)
> > 2. Object would be instanciated as :
> > new-object-name: class-name/new
<<quoted lines omitted: 5>>
> REBOL has it's own garbage collector, do we really need
> constructors and deconstructors?
Actually, a constructors might be useful to automatically assigned values to
properties... as for the deconstructors, it would'nt be necessary..
> > 4. Within class declaration, methods would be define like this :
> > method-name: func [value !refinement ref-value] [ ... ]
<<quoted lines omitted: 8>>
> rename your FUNC to METHOD, making the difference somewhat more obvious?
> Just a thought, so.
Unfortunately, I really can't use refinements as they are currently being
defined... I would have to change some implementation in my library, and
some of the code of object instance really really redundant... which I try
to minimize. Your idea of a METHOD is great... I'll look at it ;)
> Not beeing a REBOL guru in any way you eventually may find some
> suggestions in my code :)
I'll look at it with interest.
Best,
Chris
[4/7] from: jasonic:nomadics at: 8-Oct-2001 7:21
It be waaay offbase, but you may want to peek at Pyro - Python Remote
Objects. Not as a suggestion to use Python instead of Rebol, but simply good
progamming by an original programmer:
http://pyro.sourceforge.net/
./Jason
[5/7] from: chrismorency:videotron:ca at: 7-Oct-2001 4:59
Hi,
As I mentioned in another post earlier, I've been working for the past three
weeks on a pseudo class inheritance library for Rebol/Core. This would
enable rebol developers to use class to define object or class inheritance.
Why ? The current implementation of object "inheritance" under rebol is done
by a way of cloning (ie copying everything) from one object to the other.
Hmm and ? What I've been working on enable small objects (in term of memory
and method code) to refer big class (with a lot of method code).
But ? However, my implementation would require some diversions from the way
we actually code objects in rebol ! I would like to ask to those interested
in such a library if these diversions would be inappropriate to their coding
style, taste, etc...
rebol source code = [ ... ]
1. new class would be define like this :
make-class 'class-name [ ... ]
Inherited class would be define like this :
make-class/from 'class-name [ ... ] super-class-name
[ ... ] would look similar to the code we currently
use in make object! [ ... ]
2. Object would be instanciated as :
new-object-name: class-name/new
I'm thinking about adding an automatic initiation method
that would be call when instanciating an object ! What
about a destroy method...
3. Type validation would be send as :
object-name/type-of class-name
4. Within class declaration, methods would be define like this :
method-name: func [value !refinement ref-value] [ ... ]
However, during execution, refinement would be use as usual :
method-name "a value"
mathod-name/refinement "a value" "a ref-value"
5. Class within class would be declared as such
make-class 'class-name [
sub-class-within-class-name: sub-class
]
where sub-class would be previously declared.
Upon creation of a new-object/new, all sub-objects would
have new instance of sub-class by sending new to these sub-class.
6. Extremely specific use of self/method or self/value within
class-method-declaration.
self/method or self/property would refer to the instance
method or property...
self method or self property would refer to the class
method or property...
7. Specific calling of super-class within methods...
8. Current Reserved words : [class, super, self, new, type-of]
I've spent a lot of time on this, I hope some people are intersted in this
kind of library... otherwise I may return to my other project ;)
Note : the library has not been tested enough for a public release. also, it
would requires some testing by people working daily with objects in rebol,
mainly rebol gurus who could tell me if everything I'm doing is proper or
not ;) and how it could be better... or if a guru would like to take up the
project and make it better ! I'm open to suggestion !
Best,
Chris
[6/7] from: christian:ensel:gmx at: 7-Oct-2001 12:19
Hello Christian Morency,
some months ago I worked an a similiar project, you can find my code at the
bottom of this mail. It's not very complete, but it may inspire you in a way
or two :)
> As I mentioned in another post earlier, I've been working for the past three
> weeks on a pseudo class inheritance library for Rebol/Core. This would
<<quoted lines omitted: 7>>
> in such a library if these diversions would be inappropriate to their coding
> style, taste, etc...
I don't believe this to be a big problem. There are other dialects in REBOL
differing from "native" REBOL style and syntax, e.g. the dialects used for
PARSE and VID.
And now for some comments:
> 1. new class would be define like this :
> make-class 'class-name [ ... ]
>
> Inherited class would be define like this :
> make-class/from 'class-name [ ... ] super-class-name
I for a reason decided against a construct using refinements because this
would make reading your code unneccessarily hard: The specification of the
superclass as an argument to a refinement leads to code looking like
make-class/from 'class-name [
;...
;... insert hundreds of line of method code here
;...
] super-class-name
Having a special functions for deriving classes eases reading code a lot,
allowing for having 'class and 'superclass on the same line of code:
make-derived-class 'class-name 'superclass-name [
;...
;... insert hundreds of line of method code here
;...
]
What do you think?
> 2. Object would be instanciated as :
> new-object-name: class-name/new
>
> I'm thinking about adding an automatic initiation method
> that would be call when instanciating an object ! What
> about a destroy method...
Actually, I haven't thought in deep about that, but as long as REBOL has it's
own garbage collector, do we really need constructors and deconstructors?
> 4. Within class declaration, methods would be define like this :
> method-name: func [value !refinement ref-value] [ ... ]
>
> However, during execution, refinement would be use as usual :
> method-name "a value"
> mathod-name/refinement "a value" "a ref-value"
I didn't spend effort to allow for method refinements in my OOP-framework,
but IIRC there was a solution to compose function calls with refinements
on the mailing list some time ago which shouldn't be to hard to implement.
But if your refinement defining syntax differs from FUNC's style why not
rename your FUNC to METHOD, making the difference somewhat more obvious?
Just a thought, so.
> Note : the library has not been tested enough for a public release. also, it
> would requires some testing by people working daily with objects in rebol,
> mainly rebol gurus who could tell me if everything I'm doing is proper or
> not ;) and how it could be better... or if a guru would like to take up the
> project and make it better ! I'm open to suggestion !
Not beeing a REBOL guru in any way you eventually may find some suggestions
in my code :)
Kind regards,
Christian
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
REBOL [
title: "Classes & Instances"
name: %class-instances.r
author: "Christian 'CHE' Ensel"
date: 23-Aug-2001
]
context
[
;======================================= CLASS instance-spec class-spec ==
; ------------------------------
class: func
[
"Defines a user class object."
instance-spec [block!] "Code per instance"
class-spec [block!] "Code per class"
/local
new-class
]
;.........................................................................
[
new-class: make object! compose [
super-class: none
instance: (
make object! head insert instance-spec compose [class: none]
)
(class-spec)
]
new-class/instance/class: new-class
new-class
]
;-------------------------------------------------------------------------
;=================== DERIVED-CLASS super-class instance-spec class-spec ==
; --------------------------------------------------
derived-class: func
[
"Derives a user class object from an existing class object."
super-class [object!] "Class to inherit from"
instance-spec [block!] "Code per instance"
class-spec [block!] "Code per class"
/local
new-class
]
;.........................................................................
[
new-class: make super-class compose [
super-class: (super-class)
instance: (make super-class/instance instance-spec)
(class-spec)
]
new-class/instance/class: new-class
new-class
]
;-------------------------------------------------------------------------
;========================================= INSTANCE class instance-spec ==
; ----------------------------
instance: func
[
"Returns an instance object of desired class."
class [object!] "Class to belong to"
instance-spec [block!] "Instance-specific code"
/local
new-instance
]
;.........................................................................
[
new-instance: make class/instance instance-spec
]
;-------------------------------------------------------------------------
;==================================== DO-METHOD instance message /SUPER ==
; ---------------------------------
do-method: func
[
[catch]
"Dispatch a class method, throw error for unknown methods."
instance [object!] "Instance"
message [block!] {Block containing method word
and argument words, if any}
/super
"Invoke method of super-class."
/local
method
]
;.........................................................................
[
method: in either super [
instance/class/super-class
][
instance/class
] first message
if none? method [
throw make error! reduce ['script 'unknown-method first message]
]
method: get method
do compose [(:method) (instance) (next message)]
]
;-------------------------------------------------------------------------
;============================== TRY-METHOD instance message /ANY /SUPER ==
; ---------------------------------------
try-method: func
[
"Dispatch a method, do nothing for unknown methods."
instance [object!] "Instance"
message [block!] {Block containing method word
and argument words, if any}
/super
"Invoke method of super-class."
/local
method
]
;.........................................................................
[
method: in either super [
instance/class/super-class
][
instance/class
] first message
either none? method [none] [
method: get method
do compose [(:method) (instance) (next message)]
]
]
;-------------------------------------------------------------------------
;============================================ IS? class instance /EXACT ==
; -------------------------
is?: func
[
"Returns TRUE if instance is (indirect) instance of given class."
class [object!] "Class"
instance [object!] "Instance"
/exact
"Return TRUE only for direct instances of given class."
/local
instance-class
]
;.........................................................................
[
either exact [
equal? instance/class class
][
instance-class: instance/class
forever [
if equal? instance-class class [break/return true]
instance-class: instance-class/super-class
if none? instance-class [break]
]
]
]
;-------------------------------------------------------------------------
;=============================================================== IMPORT ==
; ------
import: func
[
"Expose dialect to global context."
]
;.........................................................................
[
set bind [
class derived-class instance is? do-method try-method
]
in system/words 'context reduce [
:class :derived-class :instance :is? :do-method :try-method
]
return
]
;-------------------------------------------------------------------------
;----------------------------------- SYSTEM/ERROR/SCRIPT/UNKNOWN-METHOD --
;
system/error/script: make system/error/script [
unknown-method: ["Method" :arg1 "not declared"]
]
;-------------------------------------------------------------------------
]
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
And here's an example demonstrating the use of the above:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
REBOL [
title: "Classes & Instances - Example"
name: %class-instances-sample.r
author: "Christian 'CHE' Ensel"
date: 23-Aug-2001
]
do in do %/rebol/scripts/class-instances.r 'import
do sample:
[
human!: class [
name: none
age: none
][
introduce: function [human [object!]] [] [
do-method human [say rejoin ["Hi, I'm " human/name "!"]]
do-method human [say rejoin ["I'm " human/age " years old."]]
do-method human [say "I'm human."]
]
say-to: function [human [object!] whom [object!] what [string!]] [] [
do-method human [
say rejoin [whom/name ", " lowercase/part what 1]
]
]
say: function [human [object!] what [string!]] [] [
print rejoin [human/name {: ^-"} what {"}]
]
]
man!: derived-class human! [] [
introduce: function [man [object!]] [] [
do-method/super man [introduce]
do-method man [say "And I'm a man."]
]
]
woman!: derived-class human! [] [
introduce: function [woman [object!]] [][
do-method/super woman [introduce]
do-method woman [say "And I'm a woman."]
]
bewitch: function [woman [object!] whom [object!]] [][
do-method woman [say-to whom "Eat this!"]
]
]
human: instance human! [name: "Nobody"]
adam: instance man! [name: "Adam" age: 32]
eve: instance woman! [name: "Eve" age: 27]
linda: instance woman! [name: "Linda" age: 28]
do-method adam [say "Hello, I'm Adam."] prin newline
do-method eve [say "Hello, I'm Eve."] prin newline
do-method adam [introduce] prin newline
do-method eve [bewitch adam] prin newline
do-method/super eve [introduce] prin newline
try-method adam [bewitch eve] prin newline
do-method linda [introduce] prin newline
do-method linda [say-to adam "You'd better eat this banana."]
prin newline
do-method/super linda [say-to adam "You'd better eat this banana."]
prin newline
if is? human! adam [print "Adam is a human."]
]
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
[7/7] from: christian:ensel:gmx at: 9-Oct-2001 21:16
Hello Christian,
>> No answers here but something that would definitely entyice me to use the
>> class methods!
> Hmm, I have to admit that I haven't been thinking about object over ip
> connection. However, since class are still object! and object-instance are
> object! too (in the rebol sense), I would expect to serve both class and
> object through a connection...
Whenever it comes to making OOP objects persistent - and at the very moment
I don't see too much of a difference between writing class instances to disk
and transferring them over networkobjects - there's the problem of correctly
identifing the class a object belongs to.
Now, while thinking about that today's evening I've had an idea (don't know
if someone had this idea too long before me, at least till now I never heard
of it :)
Instead of letting Joe User (Joe Developer, to be exact) name it's classes
and later watching him running into the problem of names clashing between
different developers naming different classes
using the same name, why not let the user take care of forgiving _universally_
_unique_ _class_ _names_? This could be achieved very easily if we adopt the
model XML uses for namespaces:
foo: make object! [
super: none
class: http://www.christian-ensel.de/classes/foo.r
...
]
bar: make object! [
super: http://www.foobar.com/classes/foo.r
class: http://www.foobar.com/classes/bar.r
...
]
This also may serve as a solution to the networking problem as well,
because everyone who wants to work with such class based objects knows
where to get the class definition.
Or am I missing something?
Regards,
Christian (Ensel :)
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted