From: Tom Sawyer Date: 2002-07-09T15:51:24+09:00 Subject: Re: self_parent dirk, thank you for the comprehensive investigation into the self_parent concept. it was very enlightening. after some additional thought, and still not being satisifed with any implementation i have yet divised for my problem, i have come to realize more clearly what is i am trying to accomplish. essentially what i am trying to create are non-bound, or open, Proc objects, in contrast to the type of Proc objects we can create now, which are bound to the local variables at the time of creation. I want Proc objects that get bound at the time of calling: class A def initialize(x) x.call end def display puts 'hello' end end class B def initialize(x) x.call end def display puts 'goodbye' end end x = OpenProc { display } A.new(x) --> hello B.new(x) --> goodbye in this way an object can, in effect, ask another object what it should do. and that is what i was accomplishing, albiet in a lame way, by passing self (and wanting self_parent for). so, is there any way to readily accomplish this in ruby? ~transami On Mon, 2002-07-08 at 05:28, Dirk Detering wrote: > james@rubyxml.com schrieb: > > How would an object know the methods of an arbitray parent? Doesn't this > > completly couple the two objects? The parent (reasonably) expects the > > object it creates to implement certain methods; the newly-created object > > expects the parent to implement certain methods. > > Yes, indeed. But let me think aloud a bit: > > 1.) Sometimes you have this tight coupling between two > classes/objects. Customer and Address perhaps is a bad > example as you can Address imagine to belong to other > containers too. > OTOH a relationship between an Order and an Orderline or an > Invoice and Invoiceline is much closer. > > 2.) > Designing that relationship as bidirectional navigable > (as expressible with the UML) is a possibility. > You could hand around orderlines and they keep the relation > to their container/master/whatever-term-you-want like with > closures at the technical level. > > OTOH: Wouldn't it be a better design to always hand over the > reference to the order or to the invoice instead of single > lines, and access the parts of it via the order's/invoice's > interface? (delegator). Otherwise the client of Order would > have a deep inside, how an order is implemented inside. > But: Wouldn't that mean, that an Order has to implement > something like a Orderline interface? > (As I could not easily return a reference to one of its > orderlines ...) > > This tight coupling is an intimate knowledge between > Order and Orderline, and is directly understood by people > knowing the domain. > But looking at this: Some people here stated *never* need > to pass a self reference to a contained object. This would > mean to have a strictly uni-directional navigation troughout > the whole system. > And that's IMHO not true, unless they make some design pull-ups to > strictly avoid callback and delegation. > > > Perhaps I misunderstand what you need to accomplish or how self_parent > > would be implemented, but it sounds like it would encourage fragile designs > > without any real gains. > > Hum, not really. I've got the feeling that there should always be > two kind of interfaces. > > First: The 'inner' one between two tightly coupled > classes/objects. Why shouldn't be there a relation between > a class/object and its close "environment"? > (In comparision: Think of the effort of writing a shellscript > which gots everything explicitly as CL-options instead of > using the environmentvariables.) > They would communicate with each other in a form of call and > callback. > > Second: The 'outer' one between a component and it's > environment. To be useful in many "environments", perhaps > contexts, the component should never rely on specific behaviour > or structure of its outer side. Here works the Law Of Demeter: > "Don't talk to strangers". > > In this description a 'component' can be a single class or > a combination of tightly coupled, co-relating classes. > > Looking into the real world, there *are* technical items > which can be assembled into many environments by having > a standardised "interface" (plug, switches ...) but having > parts inside them which possibly never (hum I don't like this > word) could be used outside in other combinations. > > Coming to the original subject: > - Yes, indeed it is a design decision to couple classes > So to be open, the language has to support all (hum, most of) > the decisions I made. Not necessarily language inherent (when > passing self) but it could simplify things, if it would be > possible (when having a self_composite reference, to give > another name for that ;o) ). > This is the fact with Ruby. Your design decisions are supported. > In this case by using self. > - As we've seen in the discussion in this thread, this *is* a > *design* decision and not a general feature of classes in OOP. > So this reference pointer can not be considered an every-class > feature requirement. > It is the special case the UML calls: > Composition, meaning a one-to-many aggregation. > And it is the special case this asssociation is bidirectional. > Perhaps it would be worth thinking about a keyword in the > language declaring a class as 'bidirectional', which, when > using it, would introduce this self_composite reference? > - But it would not be enough to have this keyword. You should > declare more of this relationship. So you would declare the > class to which this composition refers, to give the system > ability to proof the structure at runtime just *before* > calling a self_composite's method. > This would lead indirectly to a design language, where you > would declare associations in another way than common today. > The question then is: What about all the other kinds of > associations, what about multiplicity? > > I resume: This feature would lead to a totally other PL concept, > and leads outside of Ruby. > > > In your example, Address requires an object that implements pretty_name. > > Indeed. > > > It works with any parent if that parent passes in a pretty_name-compliant > > object. > > Right. > > > Having Address use self_parent means it *only* works when the > > parent responds (and in the right way) to pretty_name. > > Indeed, that's the problem with communication :-) . > The called object has to implement a method for the message. > > > Changing the > > Customer class can break the Address class, and vice versa. > > What you stated is a problem you *always* have when changing the > interface of a class which is used by other parts of the system > (like usual, as classes/objects *exist* to be used by other parts, > or they will be killed by the GC). > > So changing the Customer class will have much more effect > to objects not mentionted here in the current discussion: > Its clients! > > Using the self_whatever reference would not break the > rule of communication via interfaces. > It would only simplify the definition of a very special > kind of association. > > And as I told, Customer->Address is a bad example. > > Regarding to my examples: > Changing a class without knowing the relating (domain) model > (Order -> Orderline) is a foolish attempt. > When knowing the (domain) model, changing the Order class > without having a look at the Orderline class (or vice versa) > should be considered a implementor's offence. > > > BTW: Regarding the last post I read. > This is indeed not a matter of OO "inheritance". But looking > at the ways to construct systems there are *two* relation > dimensions: inheritance and association. > It is interesting, that OO languages directly support only > the former one, but have no implicit mechanisms for the latter. > This is why this relations must be explicitly 'generated' out > of an UML diagram into code mechanisms (e.g by passing self). > But these mechanisms just are flexible enough to support the > very different kind of design decisions. > > JM2C > > Det > -- ~transami "They that can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety." -- Benjamin Franklin