World Morph (was: Comments on Lex's "Object as
Capabilities in Squeak")
Mark S. Miller
markm at caplet.com
Fri Jan 31 05:49:29 UTC 2003
At 10:11 AM 1/30/2003 Thursday, Anthony Hannan wrote:
>World is the top Morph in the tree of morphs that automatically gets
>displayed and refreshed on the Screen. A button would have a parent
>morph, such as a window; the window would have a parent morph, such as
>the World. You add a morph by creating it with all its submorphs, then
>adding it to the world. For example:
>"World addMorph: (SystemWindow new addMorph: (RectangleMorph new position: 100 at 100))"
>(go ahead execute it).
Thanks, it worked. So "World" is just the root Morph in the Morph tree? That
makes sense. But then I'm confused why we have a problem. When would a
method of an object refer to World by name?
I see why the above code needs to refer to World by name: it's a top-level
expression to be doit-ed, which puts it in the same category as E
command-line expressions. The doit/printit/inspectit commands should
probably evaluate their expression in a top-level privileged scope
containing bindings representing all the user's authority, just like E
command-line expressions. (Yes, this is equivalent to what it does now, just
described in terms of the proposed distinction with the part that would
change -- the scope methods defined in, which would be a safeScope.)
(Given pure lexical rules, and methods being defined in scopes with no
authority, then all authority used in such top-level expressions will be
statically apparent, so the user-programmer has a chance of making an
informed decision on this grant of authority. Non-programmers, who can't
understand the authority implied by the code they're seeing, should probably
not use the doit/printit/inspectit commands on an image where they may
encounter example code they shouldn't trust. Alternatively, different
workspaces could be provided in which powerful authorities are absent or
virtualized. Does the doit/printit/inspectit already use a scope according
to the Workspace? If not, would this be a problem?)
However, if a method of an object contains code like your above example with
a hard coded global reference to World, then, when invoked, it will insert the
new Morphs directly under the root of the Morph tree instead of putting the
new Morphs where their instantiator or caller wants them. This is a failure of
virtualizability -- an important kind of polymorphism and late-binding.
Remember my trivial "zippy" file example. Likewise, a morph-creating-object
should have an instance variable or parameter for a parent Morph. The
object may be coded under the assumption that this parent Morph will indeed
be bound to World. But as long as the instantiator provides a Morph which
acts World-like, the object shouldn't be able to tell the difference. As far
as it's concerned, the provided Morph is the World.
Hard coded globals references to mutable state or to authority conveying
objects is a form of early binding. Morphs deserve full polymorphism!
I suspect that, even independent of security, this kind of early binding is
just bad oo programming practice.
Can you provide any examples that motivate including hard coded global
references to World inside methods of objects, other than in example,
demonstration, or testing code? I do have an installed Squeak (I'm not sure
how old) so feel free to just tell me where in the image to look. Thanks.
Text by me above is hereby placed in the public domain
More information about the Squeak-dev