Private Object Function
[1/19] from: coussement::c::itc::mil::be at: 15-Jan-2001 10:52
Hi REBOLS,
I would like to make an object function private to this object. That is:
>> o: make object! [
[ value: make integer! 1
[ ; some privatization code ...
[ add-one: does [value: value + 1]
[ get-value: does [add-one
[ print value]
[ ]
>> o/get-value
2
>> o/add-one
here I should get something like...
** Script Error: Invalid path value: add-one.
** Where: o/add-one
Any idea ? Of course the principle could be extended to the privatization of
variables...
Thx a lot,
Best Regards,
chr==
[2/19] from: rebol:techscribe at: 15-Jan-2001 11:16
Hi Christophe,
I think your description is incomplete. By privatization do you mean
1. that functions within the object should/should not have access to the
privatized function?
2. If 1, then that limits how hidden the hidden function is. Recall that
REBOL functions are editable during runtime. This means that I can use
any function that accesses the hidden function as an entry point into
the hidden function. I.e.
o: make object! [
hidden-func: does []
exposed-func: does [hidden-func]
]
exposed-hidden-func: get first second get in o 'exposed-func
3. Should the function have access to other functions and words defined
in the context of the object?
4. Should the object be serializable including hidden functions?
5. Should descendants have access to hidden functions?
Without clarifying these questions I can see a long thread of rejected
proposals.
Take Care,
Elan
CRS - Psy Sel/SPO, COUSSEMENT Christophe, CPN
wrote:
[3/19] from: g:santilli:tiscalinet:it at: 15-Jan-2001 20:39
Hello COUSSEMENT Christoph!
On 15-Gen-01, you wrote:
CC>>> o/add-one
CC> here I should get something like...
CC> ** Script Error: Invalid path value: add-one.
CC> ** Where: o/add-one
The most recent /Core experimental allows you to write:
o: make object! [
; public
get-value: none
; private
make object! [
value: make integer! 1
add-one: does [value: value + 1]
set 'get-value does [
add-one
print value
]
]
]
or:
o: make object! [
; public
get-value: none
; private
use [value add-one] [
value: make integer! 1
add-one: does [value: value + 1]
get-value: does [
add-one
print value
]
]
]
Regards,
Gabriele.
--
Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer
Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
[4/19] from: rebol:techscribe at: 15-Jan-2001 13:13
Hi Gabriele,
how is this any ifferent from what you can do with the current stable
version (2.3)?
The questions, however, remain.
a) The protection can be circumvented, in as much as I can use
get-value's body to access add-one as well as value.
b) The object o cannot be serialized together with the hidden words.
BTW, Christoph, what are you trying to accomplish?
Take Care,
Elan
I can still access "private"
Gabriele Santilli wrote:
[5/19] from: coussement:c:itc:mil:be at: 16-Jan-2001 9:34
> Hi Christophe,
> I think your description is incomplete. By privatization do you mean
<<quoted lines omitted: 9>>
> ]
> exposed-hidden-func: get first second get in o 'exposed-func
[ok, I can also use this]
> 3. Should the function have access to other functions and words defined
> in the context of the object?
[yes, it should]
> 4. Should the object be serializable including hidden functions?
[I do not understand 'serializable' ?]
> 5. Should descendants have access to hidden functions?
[yes they should. Although it should be interressant to me to have a
mean to control this: some sort of 'protected function' which is known to
the ancestor, but not to the child objects...]
> Without clarifying these questions I can see a long thread of rejected
> proposals.
[the 'private function' I meant is the opposite of a 'public
function'.
That is, a private function is a function only known and accessible
from within the context of the object. A public one is part of the public
interface of the object and is therefore accessible from outside the object,
by another object from exemple]
[6/19] from: coussement:c:itc:mil:be at: 16-Jan-2001 9:49
> Hi Gabriele,
> how is this any ifferent from what you can do with the current stable
<<quoted lines omitted: 4>>
> b) The object o cannot be serialized together with the hidden words.
> BTW, Christoph, what are you trying to accomplish?
[In the context of the project I'm working on I would like to
implement a coherent OODBMS - which I announce in the list sometime ago. For
this I need to restrict the access to the object's internal implementation.
I should be able to determine which methods can be accessed from the
outside, which not, which should be inherited or not. The solution should
also be applicable for protecting object's properties.
Regards,
chr==]
[7/19] from: coussement:c:itc:mil:be at: 16-Jan-2001 9:56
> Hello COUSSEMENT Christoph!
> On 15-Gen-01, you wrote:
<<quoted lines omitted: 30>>
> ]
> ]
[thanks for answering !
it works fine to me, but it does not simplify and clarify the
writing of the code, in that way that the body of the 'public function' must
be found back into the 'private' part, due to the runtime binding...
Anyway, it's my best solution for now ;-)
best regards,
chr==
]
[8/19] from: rebol:techscribe at: 16-Jan-2001 1:56
Hi Christophe,
> > 4. Should the object be serializable including hidden functions?
> [I do not understand 'serializable' ?]
By "serializable" I mean that: If I have the object (including its
private components) loaded in memory, should I be able to write the
object including its private components to a file? Or is it sufficient
if I only write the public components of the object to a file? I.e.
o: make object! [something: none]
write %filename.ext mold o
will write this object to a file.
If I add private components to this object, and I want to write the
object to a file, should the private components be written along with
the object? Or should the object be written without the private
components, which means that when the object is subsequently loaded from
this file, it will not include the private components.
> > 5. Should descendants have access to hidden functions?
> [yes they should. Although it should be interressant to me to have a
> mean to control this: some sort of 'protected function' which is known to
> the ancestor, but not to the child objects...]
Is this "protected" function in addition to the private function? If
not, then I don't see how descendants can access the hidden function, if
this hidden function is not known to descendants.
> That is, a private function is a function only known and accessible
> from within the context of the object. A public one is part of the public
> interface of the object and is therefore accessible from outside the object,
> by another object from exemple]
Basically, my question is, to what degree do you want to enforce this?
Is it
a) more an organizational principle to help you as a programmer organize
your code;
b) you don't want the private functions/words to show up in the block
returned by first object, but if a non-member function absolutely wants
to, then it will
will be able to also access hidden words ...
c) Under no circumstances must a non-member function be able to access
private components?
That's, basically what I'm asking
Take Care,
Elan
[9/19] from: rebol:techscribe at: 16-Jan-2001 2:00
Hi Christophe,
> I would like to
> implement a coherent OODBMS - which I announce in the list sometime ago.
I just checked my REBOL folder, and I don't appear to have that one.
Could you send me the email you are referring to offlist? It may help me
understand where you are heading with this. If it's to be an OODBMS then
my guess is that you won't be served with a solution that prevents you
from storing the private components of an object together with the
object?
Take Care,
Elan
[10/19] from: coussement:c:itc:mil:be at: 16-Jan-2001 16:07
Elan:
> > > 4. Should the object be serializable including hidden functions?
> > [I do not understand 'serializable' ?]
<<quoted lines omitted: 4>>
> o: make object! [something: none]
> write %filename.ext mold o
[thanks, I didn't know this one. I used 'save to keep the object
structure intact...]
> will write this object to a file.
> If I add private components to this object, and I want to write the
> object to a file, should the private components be written along with
> the object? Or should the object be written without the private
> components, which means that when the object is subsequently loaded from
> this file, it will not include the private components.
[In the specific context of my try for OODBMS development, the
persistence of the DBobject should indeed request to be written down
INCLUDING the private methods, because those should contain some business
intelligence needed to access/handle the contained data]
> >
> > > 5. Should descendants have access to hidden functions?
<<quoted lines omitted: 6>>
> not, then I don't see how descendants can access the hidden function, if
> this hidden function is not known to descendants.
[you're right ! methods would be classified in three exclusives
classes: public, private and protected
Sample use of them could be:
- public access : the method can be called from any script in the
application.
- private access : the method can be called only from scripts in the
object for which the function was declared (including the sub-objects); the
method cannot be called from descendant of the object.
- protected access : the method can be called only from scripts for
the object for which the function was declared, and its descendant.
!!! ATTENTION !!! After studying some more documentation I
collected, I've noticed that I interverted the meaning of the concept
'private' and 'protected' : that's why the definitions above doesn't mach
anymore what I previously said. Sorry for the inconvenient. ]
> > That is, a private function is a function only known and
> accessible
<<quoted lines omitted: 13>>
> c) Under no circumstances must a non-member function be able to access
> private components?
[as I see the implementation for now, my meaning of it is to enforce
the protection of the object's contain by keeping the protected/private part
out-of-bound for the context from which the object is called. That is, using
your words, your point c).
Creating highly encapsulated objects organize for sure the code, but
more important allows you to completely control any modification and access
to properties and methods, which is important in the process of creating
waterproof applications...
]
> That's, basically what I'm asking
[I hope you'll find my answers satisfying.]
> Take Care,
[Thank you for caring ;-)) ]
> Elan
[
Best regards,
chr==
]
[11/19] from: coussement:c:itc:mil:be at: 16-Jan-2001 16:13
> > I would like to
> > implement a coherent OODBMS - which I announce in the list sometime ago.
>
> I just checked my REBOL folder, and I don't appear to have that one.
[it was just my answer to a question of Mr. Gabriele Santilli, where
he ask if anyone was interrested in building a DB system. I just mentionned
my interess foran OODBMS ]
> Could you send me the email you are referring to offlist? It may help me
> understand where you are heading with this. If it's to be an OODBMS then
> my guess is that you won't be served with a solution that prevents you
> from storing the private components of an object together with the
> object?
[right again ! for further details, please refer to my answer to
your other mail of today]
> Take Care,
[U2 :-) ]
> Elan
[best regards,
chr==
]
[12/19] from: g:santilli:tiscalinet:it at: 16-Jan-2001 19:36
Hello Elan!
On 15-Gen-01, you wrote:
E> how is this any ifferent from what you can do with the current
E> stable version (2.3)?
That makes 2.3 (and all the versions before latest experimental)
crash after a recycle.
E> The questions, however, remain. a) The protection can be
E> circumvented, in as much as I can use get-value's body to
E> access add-one as well as value. b) The object o cannot be
E> serialized together with the hidden words.
This is true. But it is not a problem usually. You're not trying
to protect secret code, you're just trying to avoid accidental use
of a word meant to be private; this is useful for team projects,
or to separate interface from implementation.
Regards,
Gabriele.
--
Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer
Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
[13/19] from: rebol:techscribe at: 16-Jan-2001 21:54
Hi Gabriele,
you're right (just tried it). I thought it had already been repaired in
2.3? Must've been the later experimental versions.
Thanks,
Elan
[14/19] from: coussement:c:itc:mil:be at: 17-Jan-2001 10:40
> 1. I think the DBMS I developed in my REBOL book (REBOL The Official
> Guide) may be a starting point (chapters 15-18). It's not the "last
> word" in developing a dbms under REBOL, but it does provide some
> thoughts and examples that may be useful for you. I think the Object
> Navigator might come in handy.
[I already read it. Great book. it taught me REBOL...]
> You appear to follow the Object Pascal (Delphi) conventions.
[IMHO those are just general conventions within OO analysis and
development. For sure I didn't find them out !]
> > - private access : the method can be called only from scripts in
> the
> > object for which the function was declared (including the sub-objects);
> the
> > method cannot be called from descendant of the object.
>
> Hidden objects or contexts are not protected from descendants.
[Do you mean by this it shouldn't be possible to implement it in
REBOL ?]
>
> See what I wrote above. If you enforce c) then you cannot use REBOL's
> default functions for saving an object from outside of the object. The
> serialization functions included IN objects can - of course - make use
> of write and save.
[It's the way I already followed. I will couple this approach with
subobject or 'use for enforcing privacy.]
> Note that - as demonstrated - it is possible to get at the hidden
> stuff, if you go out of your way to do so.
[the meaning of all this is to protect code from accidental use, not
to enforce paranoia ! So I think your approach is all OK ...]
> The solution IMHO is to implement your own objects and supporting
> function in which you enforce private/protected/public rules. As long as
> your code does not use REBOL's built-in functions to violate these
> rules, you're fine, provided you don't mind the extra overhead.
[Thanks a lot for your good advises !
BTW is there anybody interested by the results I will get ? I do not
want to spam the list with uninteresting stuff...
Best Regards,
chr==
]
[15/19] from: al:bri:xtra at: 17-Jan-2001 23:33
> BTW is there anybody interested by the results I will get ? I do not want
to spam the list with uninteresting stuff...
I'm interested.
Andrew Martin
Oo Look Rebool...
ICQ: 26227169 http://members.nbci.com/AndrewMartin/
[16/19] from: rebol:techscribe at: 17-Jan-2001 11:43
Hi Christophe,
> > Hidden objects or contexts are not protected from descendants.
> [Do you mean by this it shouldn't be possible to implement it in
> REBOL ?]
No, I mean that using REBOL's default inheritance mechanism, i.e.
>> o: make object! [foo: none make object! [bar: does ["I'm hidden"] set 'foo does [bar]
] ]
>> p: make o [foobar: "I'm p"]
p will have inherited foo as a functions that successfully calls bar
just like o does. This leads to the following situation. Given:
>> o: make object! [
foo: none
set-bar: none
make object! [
bar: none
set 'foo does [bar]
set 'set-bar func [value] [ bar: value ]
]
]
>> p: make o []
>> o/set-bar "I was set by o."
>> print ["o/foo" mold o/foo]
o/foo "I was set by o."
>> print ["p/foo" mold p/foo]
p/foo "I was set by o."
>> p/set-bar "I was set by p."
>> print ["o/foo" mold o/foo]
o/foo "I was set by p."
>> print ["p/foo" mold p/foo]
p/foo "I was set by p."
Note that - unlike your requirements for private values - p and o share
o's private value bar. REBOL's inheritance mechanism acts in a
protected
way with respect to children's access to hidden object
properties.
This means that you should really implement your own custom object
mechanism, let's call it class mechanism to separate it from REBOL's
objects, which may be built on top of objects.
class!: make object! [
private: none
published: none
public: none
]
some-class: class class! [
private [
pa: none
pb: none
]
published [
ua: none
ub: none
]
public [
la: none
lb: none
]
]
class: func [ spec [block!] /local new-class] [
set [_ private-block _ published-block _ public-block] spec
return make object! [
private: make object! private-block
published: make object! published-block
public: make object! public-block
]
]
some-child: clone some-class
clone: func [parent [object!] /local result] [
; has to be written. I don't have the time right now.
; what takes a little more time is that you must account
; for possible complex structures such as classes embedded
;in a class, or blocks of objects/classes embedded ...
; If nothing useful pops up on the mailing list perhaps I'll implement
something this evening
]
> BTW is there anybody interested by the results I will get ? I do not
> want to spam the list with uninteresting stuff...
Well, as you've guessed by now, I'd even be interested in contributing
some code. I think it'd be an interesting ongoing public project.
Take Care,
Elan
[17/19] from: rebol:techscribe at: 17-Jan-2001 22:43
I was really in a hurry when I wrote this stuff. The class function I
included was untested and incorrect. The corrected version is:
class: func [ default! [object!] spec [block!] ] [
set [_ private-block _ published-block _ public-block] spec
return make default! [
if private-block [private: make object! private-block]
if published-block [published: make object! published-block]
if public-block [public: make object! public-block]
]
]
A better version is:
class: func [[catch] default! [object!] spec [block!] /local
class-spec] [
class-spec: make block! 6
foreach [section definition] spec [
either block? definition [
insert class-spec compose/deep [
(to set-word! section) make object! [(definition)]
]
][
throw make error! join {Expected definition of type block!.
Received } [mold definition " of type " mold type? definition "
instead."]
]
]
return make default! class-spec
]
The second version is more flexible in that it permits spec blocks that
exclude any or all of the exposure signifiers (public, published, or
private), the declarations may occur in any order, and it catches
incorrect definitions.
Hope this helps,
Elan
[18/19] from: rebol:techscribe at: 16-Jan-2001 14:26
Hi Christophe,
1. I think the DBMS I developed in my REBOL book (REBOL The Official
Guide) may be a starting point (chapters 15-18). It's not the "last
word" in developing a dbms under REBOL, but it does provide some
thoughts and examples that may be useful for you. I think the Object
Navigator might come in handy.
2.
> [In the specific context of my try for OODBMS development, the
> persistence of the DBobject should indeed request to be written down
> INCLUDING the private methods, because those should contain some business
> intelligence needed to access/handle the contained data]
You want strictly enforced privacy, and you want the ability to save
objects including their private componenets. From the point of view of
privacy enforcement REBOL's built-in storage functions (write, save) are
non-members that are prohibited from accessing the private components.
If they are prevented from accessing the private components, how should
they be able to save these private components, unless they are used from
within member functions? The OODBMSs I am aware of use two strategies to
save objects:
a) Each object includes serialization functions used to store the
object. Since the serialization functions are members of the object,
they do have access to private object conponents. This can be
implemented in REBOL.
b) The OODBMS uses runtime system information (RTTI) to invade the
privacy of the object and automatically determine the components and
component types of an object. This can also be implemented in REBOL.
> [you're right ! methods would be classified in three exclusives
> classes: public, private and protected
You appear to follow the Object Pascal (Delphi) conventions.
> Sample use of them could be:
> - public access : the method can be called from any script in the
> application.
This is supported in REBOL using paths, or GETting a value IN an object
(i.e. get in object 'word).
> - private access : the method can be called only from scripts in the
> object for which the function was declared (including the sub-objects); the
> method cannot be called from descendant of the object.
Hidden objects or contexts are not protected from descendants.
> - protected access : the method can be called only from scripts for
> the object for which the function was declared, and its descendant.
Hidden objects or contexts are exposed to descendants.
> > c) Under no circumstances must a non-member function be able to access
> > private components?
> [as I see the implementation for now, my meaning of it is to enforce
> the protection of the object's contain by keeping the protected/private part
> out-of-bound for the context from which the object is called. That is, using
> your words, your point c).
See what I wrote above. If you enforce c) then you cannot use REBOL's
default functions for saving an object from outside of the object. The
serialization functions included IN objects can - of course - make use
of write and save.
Example:
>> o: make object! [
e: none
save-me: func [filename] [write/append filename mold self]
make object! [
h: does [print "I'm hidden."]
set 'e does [h]
append second save-me [write/append mold self]
]
]
>> probe o
make object! [
e: func [] [h]
save-me: func [filename][write/append filename mold self write/append
filename mold self]
]
save-me looks like its saving self twice. These are two different selfs.
The first self is bound in the context of the public object, the second
self is bound int the object used to hide the h function. I.e. the
second self evaluates to the "hidden" object. We can see that by
retrieving the body of the save-me function: get second in o 'save-me,
and then getting and displaying the two self words, using get second ...
and get fourth ... respectively, to get the value associated with the
second word (self), and the fourth word (self) in the block:
>> print mold get second second get in o 'save-me
make object! [
e: func [][h]
save-me: func [filename][write/append filename mold self write/append
filename mold self]
]
>> print mold get fourth second get in o 'save-me
make object! [
h: func [][print "I'm hidden."]
]
Note that - as demonstrated - it is possible to get at the hidden
stuff, if you go out of your way to do so.
The solution IMHO is to implement your own objects and supporting
function in which you enforce private/protected/public rules. As long as
your code does not use REBOL's built-in functions to violate these
rules, you're fine, provided you don't mind the extra overhead.
Take Care,
Elan
[19/19] from: coussement:c:itc:mil:be at: 22-Jan-2001 8:57
> I was really in a hurry when I wrote this stuff. The class function I
> included was untested and incorrect. The corrected version is:
<<quoted lines omitted: 28>>
> incorrect definitions.
> Hope this helps,
[Thanks, Elan, for this contribution.
I will try to publish on a regular base the results I get.
I will try to find a way to bypass the standard REBOL inheritence
mechanism so I can implement private functions.
BTW, I went to your site this sunday. Great look ! I like the letter
type you use ;-)
Kind Regards,
chr== ]
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted