[Zope] Methods - inheritence vs acquisition

Jeff Hoffman jeff.hoffman@goingv.com
Tue, 7 Mar 2000 22:03:17 -0500 (EST)


On Tue, 7 Mar 2000, Cary O'Brien wrote:

> Ok, I've gotten pretty far with Zope this time.  But (of course), I've
> got a bunch of questions.  Starting with...
> 
> 1)  What is the algorithm for determining which method to call?  The
>     DTML documentation says
> 
>   "attributes, including inherited and
>    acquired attributes, of the client passed 
>    in the call to the document template are searched"
> 
>    But in what order?   There can be an index_html in the class, in a parent
>    class, or somewhere up the acquisition tree.  Which takes precedence?
>    Does the product that a ZClass have anything to do with the search?
>    What about Z-Super-Classes?  Inquiring minds want to know.

I would have to research this to give a precise answer. Basically, it all
depends on the current contents of the namespace stack. Generally, this
will search REQUEST first. Next, we look to the object containing the
method being rendered. Then, the object containing that object, etc.
Whenever a ZClass is queried for an attribute and doesn't have it, it
looks to its parent(s).

> 1a) Why can't I have a method in a ZClass, but then override it in
>    the instance?  I.E. (Gaak, it has been a while since I've had to
>    even think about C++) virtual methods?  (Or have I got that wrong).

I made this mistake when first working with ZClasses, too. If you think
about it a little, you'll realize that, virtual or not, you cannot
customize an OBJECT in C++, only a CLASS. i.e.:

---
class A
{
public:
  int x;

public:
  A() { x = 0; }
};

class B : public A
{
public:
  int y;

public:
  B() { y = 0; }
};

A* objectA = new A();
B* objectB = new B();

objectA->x = 1; // Valid
objectB->y = 2; // Valid
objectA->y = 2; // Invalid, because class A has no such attribute.
objectB->z = 3; // Invalid, because class B has no such attribute.
---

If you want to customize an object (instance), you have to extend its
class, first.

In Python, this is not (really) true. Any old object is a dictionary, so
yuo can add attributes to it on the fly. Thus, the question, how can we do
this with ZClasses?

I wrote a base class that overloads ObjectManager's _checkId method to
allow instances of a ZClass to be customized. It looks like this:

---
from OFS.ObjectManager import bad_id

class Overridable:
    def _checkId(self, id, allow_dup = 0):
        if not id:
            raise 'Bad Request', 'No id was specified'

        if bad_id(id) != -1:
            raise 'Bad Request', (
                'The id %s contains characters illegal in URLs' % id)

        if id[0] == '_':
            raise 'Bad Request', (
                'The id %s is invalid - it begins with an underscore' %
id)

        if not allow_dup:
            if hasattr(self, 'aq_base'):
                self = self.aq_base
            if self.__dict__.has_key(id):
                raise 'Bad Request', (
                    'The id %s is invalid - it is already in use' % id)
---

This is not foolproof (it allows you to override TOO much, i.e. you can
create a method with the same name as a property), but it shows the idea.
I just subclass my ZClasses from this class, and I can customize each
instance individually.

[snip]

> Enough for now...

Hope this helps. Gotta run.

--Jeff

---
Jeff K. Hoffman                                         704.849.0731 x108
Chief Technology Officer                                mailto:jeff@goingv.com
Going Virtual, L.L.C.                                   http://www.goingv.com/