in reply to Re^4: Re-blessing || Re-constructing objects
in thread Re-blessing || Re-constructing objects

But what if the the classes are intentionally written and maintained with this in mind?

Then I'd ask why you wrote this code as OO, since you aren't getting a major benefit of OO: abstraction.

There are many common approaches for doing the kind of thing you describe that don't require breaking encapsulation. They're so common that they have design pattern names, like "decorator" (wrap one object with another), or "strategy" (delegate the handling of certain methods to different objects determined at runtime). You could also just use the original object's public API to get the data to populate the new objects (a "factory" pattern).

  • Comment on Re^5: Re-blessing || Re-constructing objects

Replies are listed 'Best First'.
Re^6: Re-blessing || Re-constructing objects
by blogical (Pilgrim) on Apr 18, 2006 at 04:30 UTC

    Here's a detraction I've missed so far: using classes like this doesn't easily lend itself to more than one volitile layer at a time, and so using internal objects would have an advantage in that respect, as they can be swapped whenever, in any order. Class change seems in line with more fundamental shifts in the nature of the object. At times, perhaps farming out work to a seperate object that you work indirectly with is a little excessive when you can cut out the abstraction layer by designing the classes that fill that space to the same specs. If the classes all rely on the same parent class but represent the differences between objects with the same parent, then switching classes is exactly the sort of abstractive exploit OO is designed to allow. Perhaps my thinking is incorrect, and I welcome correction.

    You need to know what type of object to plug into a given role- this doesn't require knowledge of the object's data structure, but does require setting aside a space for that object inside the larger whole and knowing how to interact with it. It needn't know how to interact with the rest of the structure outside it's own space. Any object that you plug in needs to follow the same rules- fit into the same space and allow the same manner of interaction.

    You've got to design or find a class that you can assign to manage that space within your greater object, and it has to share methods of interaction with other classes that might fill the same role, and respond in the same way (or you need to put an abstracting layer between the two as glue). So far, this seems like it could be addressed with either an independant object or an additional class layer.

    But the class can't safely make assumptions about what is outside it's own space unless you are able and desire to take any extra effort to make it so. Breaking encapsulation, and the pros and cons, is beaten to death elsewhere. But you needn't break encapsulation, if you restrict yourself to that space you know is assigned to you. You just need to allow, or even expect, that you might find data there you didn't create or put there- and maybe that's OK. In fact, maybe it's more than OK.

    I recognize the benefit of reading up on patterns. Are these particular patterns all presented in the gang of four book, or can you suggest another?

Re^6: Re-blessing || Re-constructing objects
by demerphq (Chancellor) on Apr 18, 2006 at 10:26 UTC

    Then I'd ask why you wrote this code as OO, since you aren't getting a major benefit of OO: abstraction.

    Dont you think thats a bit extreme? Simply because you have tight coupling doesnt mean you have sacrificed abstraction. If you can even speak of such a thing in such a way. For instance tight coupling between two classes doesnt mean that you lose any interface abstraction on the objects themselves. If A and B are tightly coupled C need not even know or care about one of them, and treat the other as simply and abstract interface.

    I think it really depends on which attributes of OO you think are most important. If you think that inheritance support is the objective then I can see why tight coupling of two classes would bother you. You can't easily subclass[1]. But if you are more concerned with interface abstraction then it makes no difference. And personally ive found that interface abstraction (polymorphism) is much more commonly depended on than inheritance. If you are sane you only subclass things are designed to be subclassable in the first place. Especially in perl.

    [1]: This is not strictly true. If both classes defined a sister_class property that returned the other classes name, then the tight coupling could be overriden. If you wanted to subclass either youd have to subclass both. Or you could pass the other classes name back and forth as parameters. This would mean the coupling was a lot weaker. IMO whether it made sense would depend on the circumstances.

    ---
    $world=~s/war/peace/g

      How can you have any abstraction between two classes if an existing object of one can be blessed into the other? That isn't using the public API; it's knowing the full gory details of the implementation. Otherwise, how could you know it would work to bless from one to the other?

        If they both support the same interface it makes no difference to you. For instance you are told that you can use methods X and Y and both classes support the method.

        Its exactly the same idea when you have something that says "i can use any object that supports a print method to do output". It doesnt care about the class of the object, it cares about the interface of the object.

        As for the two classes knowing about each others internals well, thats just life. Do you think there is something wrong with File::Spec because it is tightly coupled to the File::Spec::OSTYPE modules? And do you think that File::Spec somehow presents a loss of abstraction? IMO thats a good example where a set of tightly coupled modules provides a clean abstraction layer.

        ---
        $world=~s/war/peace/g

Re^6: Re-blessing || Re-constructing objects
by adrianh (Chancellor) on Apr 18, 2006 at 13:58 UTC
    Then I'd ask why you wrote this code as OO, since you aren't getting a major benefit of OO: abstraction.

    Because I want to take advantage of another benefit of OO - polymorphism?

    There are many common approaches for doing the kind of thing you describe that don't require breaking encapsulation.

    Yup. But sometimes adding that extra layer of indirection makes things harder to understand rather than simpler, and sometimes breaking encapsulation of implementation doesn't hurt anybody.

    I agree that reblessing is usually a sign of a design gone wrong - but sometimes it is the simplest solution. And that's fine with me as long as it doesn't get in the way elsewhere.

      The person trying to debug this code later may not agree that doing something so strange and unexpected just to save a few lines was worth it.
        The person trying to debug this code later may not agree that doing something so strange and unexpected just to save a few lines was worth it.

        Possibly. But the very few occasions I have used the technique the motivation hasn't been to save lines of code. It's been to provide a simpler and clearer solution than the alternatives. I can only hope I succeeded.