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

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

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

Replies are listed 'Best First'.
Re^9: Re-blessing || Re-constructing objects
by perrin (Chancellor) on Apr 18, 2006 at 11:29 UTC
    No, we're not talking about clients of these classes, we're talking about the re-blessed classes themselves. They have no abstraction from each other's internals.

    If I want to make a print_document() method in class Spreadsheet and class WebPage, and sometimes re-bless Spreadsheet into WebPage, that means both classes have to implement print_document() to access the same internal data structures. You can't decide that WebPage would be better off storing things in a tree and Spreadsheet would be better storing them in a HoA, because one might magically become the other at any time, and your methods still have to work.

      we're talking about the re-blessed classes themselves. They have no abstraction from each other's internals.

      I dont see why thats a given. But having said that, i do agree most likely the two classes would know about each others internals. Otherwise why would you even bother with the reblessing?

      If I want to make a print_document() method in class Spreadsheet and class WebPage, and sometimes re-bless Spreadsheet into WebPage, that means both classes have to implement print_document() to access the same internal data structures.

      Why is it necessary that they access the same data structures. Prior to rebless the internals structures could be converted? And even if it were necessary, why would it be a problem? Put the code that handles print_document() in one class, then the two classes that play rebless games inherit from that. If print_document itself only uses defined accessors to access its internal state theres no problem.

      You can't decide that WebPage would be better off storing things in a tree and Spreadsheet would be better storing them in a HoA, because one might magically become the other at any time, and your methods still have to work.

      You make it sound like if you aren't careful you are going to accidentally end up with code that alters it state by reblessing. Obviously you aren't. Its a technique that has specific characteristics which only make sense for certain types of problems. When you are dealing with such problems reblessing is a useful tool. You cant just write something off as a maintenance nightmare simply because the code reblesses itself. If the code has good reasons to do so and is properly documented then it should be no issue.

      I gave some examples elsewhere in this thread but to recap: things like delayed instanstiation, caching, object seriliazation ("freezing") are problems where reblessing can represent a reasonable solution.

      An example might be you have a graph of nodes that contain data that is expensive to calculate and large to store. You have to traverse the network and perform operations on the objects in some arbitrary sequence which maybe involve you visiting certain nodes much more often than others. Calculating the overall graph is also expensive. You don't have enough memory to store more than a fraction of the objects at one time.

      In a situation like this one solution would be to define two classes, one which represents the lite version of a node and one that represents the heavy version. The lite version basically does nothing but turn itself into the heavy version and then redirect the method call (plus some minor infrastructure to handle the LRU cache). The heavy version then has a method that allows it convert itself back to the lite version. Now the code traversing the network doesnt have to know anything about the caching. For all it knows the graph contains only "heavy" objects.

      A last comment... I've seen it said that any time you write an 'if' statement you aren't doing OO. If so then I think reblessing represents a clean of way of dealing with an if statement that need be executed only once.

      # just for fun ;-) sub O::v { bless $_[0],'o'; 0 } sub o::v { bless $_[0],'O'; 1 } my $o=bless {}, 'o'; print $o->v for 1..10;
      ---
      $world=~s/war/peace/g

        Why is it necessary that they access the same data structures.

        Won't there be shared code that accesses internal data? Or code in one class that accesses data set by the other class?

        Prior to rebless the internals structures could be converted? And even if it were necessary, why would it be a problem?

        What are you gaining by re-blessing then? Sounds like you want to just read the data and make a new object.

        Put the code that handles print_document() in one class, then the two classes that play rebless games inherit from that. If print_document itself only uses defined accessors to access its internal state theres no problem.

        If these defined accessors are written to work with different internal structures, how can they work on the same data? If someone re-blesses an existing object from one class to the other, they still have to work. All you're doing here is pushing the problem around from one method to another.