Achieve pure object oriented design in Ruby

Hi,

I have 3 classes A, B and C; I want to achieve following behavior (I am
calling it "pure object oriented designing") with them.

1. An instance of Class C should not exist without instance of Class B
and instance of Class B should not exist without instance of Class A.

2. Class A should be the only class accessible externally, i.e. one
should not be able to create/modify/delete instances of class B and class C
outside the scope of class A.

3. For modifying member variables of class B and class C, an external
client should use class A.

4. class A has multiple instances of class B associated with it and
similarly class B has multiple instances of class C associated with it.

Following are the classes with required methods and variables;

class A

#array of objects of class B associated with this instance

     @b_objs

#method to create instance of B and add it to above array

#methods to modify member variables of an instance of B and C (class C is
defined below)

end

class B

@b1

@b2

#array of objects of class C

     @c_objs

#method to create instance of C and add it to above array

#methods to modify member variables of an instance of C

end

class C

@c1

            @c2

end

How would I achieve 4 points listed above?

One solution I thought was to have nested classes as below,

Class A

   Class B

            Class C

            end

   end

end

above approach satisfies all the points, but for point 3 above(For modifying
member variables of class B and class C, an external client should use class
A), there would be an overhead of adding a large number of wrapper methods
for members of classes B and C.

Is there any cleaner solution in ruby by which I can achieve above
requirements?

I'm a little bummed no-one's tried to answer this. I have no idea how to do it, but the big question in my head is "why?".
From a theoretical perspective, encapsulation like this does seems kind of neat. But it sounds like it would make unit testing nearly impossible, which causes some practical issues.

For my own curiosity, is this just something you're trying as an exercise? Are you mimicking something that's common practice in another language?

-Mat

···

On Jun 19, 2006, at 9:00 AM, NAYAK wrote:

Hi,

I have 3 classes A, B and C; I want to achieve following behavior (I am
calling it "pure object oriented designing") with them.

1. An instance of Class C should not exist without instance of Class B
and instance of Class B should not exist without instance of Class A.

2. Class A should be the only class accessible externally, i.e. one
should not be able to create/modify/delete instances of class B and class C
outside the scope of class A.

3. For modifying member variables of class B and class C, an external
client should use class A.

4. class A has multiple instances of class B associated with it and
similarly class B has multiple instances of class C associated with it.

[snip: example code]

Is there any cleaner solution in ruby by which I can achieve above
requirements?

# This is still very abstract. For instance, you'll need to program some
# logic for deciding which children get forwarded requests, etc. Also, I've
# used ( *args, &block ) as parameter/argument lists a lot. You'll want to
# specialize those to your actual usage.

class A
  def initialize
    @b_objs = []
  end

  def add_b( *args, &block )
    @b_objs << B.new( *args, &block )
  end

  # delegation to one of the b_objs
  def b1( *args, &block )
    choose_b( *args, &block ).b1
  end

  def b2( *args, &block )
    choose_b( *args, &block ).b2
  end

  def add_c( *args, &block )
    choose_b_for_c( *args, &block ).add_c( *args, &block )
  end

  def c1( *args, &block )
    choose_b_for_c( *args, &block ).c1
  end

  def c2( *args, &block )
    choose_b_for_c( *args, &block ).c2
  end

  protected
  def choose_b( *args, &block )
    # put logic here for determining which b_obj matches the parameters.
    # Example:
    @b_objs.first
  end

  def choose_b_for_c( *args, &block )
    # put logic here for determining which b_obj contains the c_obj that
    # matches the parameters. Example:
    @b_objs.first
  end
end

class B
  attr_reader :b1, :b2

  def initialize
    @c_objs = []
  end

  def add_c( *args, &block )
    @c_objs << C.new( *args, &block )
  end

  # delegation to one of the c_objs
  def c1( *args, &block )
    choose_c( *args, &block ).c1
  end

  def c2( *args, &block )
    choose_c( *args, &block ).c2
  end

  protected
  def choose_c( *args, &block )
    # put logic here for determining which c_obj matches the parameters.
    # Example:
    @c_objs.first
  end
end

class C
  attr_accessor :c1, c2
end

# Jacob Fugal

NAYAK wrote:

A), there would be an overhead of adding a large number of wrapper
methods
for members of classes B and C.

I haven't had time to think through it completely, but what if you
overrode method_missing in A? Your method_missing could find out if
B.responds_to? the message, and if so, send() it the message along with
the original arguments.

Just a thought.

Jeff
softiesonrails.com

···

--
Posted via http://www.ruby-forum.com/\.

> Hi,
>

---- SNIP

I resisted, but as you insist I will explain why *I* did not answer.

I think, but I do not have the time to verify, that it is *theoretically*
impossible.

I was sure to give a convenient solution where one can still create B and C
objects but only difficultly, kind of assuring that nobody will create them
by error, and...

... failed to come up with a sensible solution.

As yourself, I would like to see some nice meta trick here, I did not come
up with it :frowning:

Robert

From a theoretical perspective, encapsulation like this does seems

···

On 6/20/06, Mat Schaffer <schapht@gmail.com> wrote:

On Jun 19, 2006, at 9:00 AM, NAYAK wrote:
kind of neat. But it sounds like it would make unit testing nearly
impossible, which causes some practical issues.

For my own curiosity, is this just something you're trying as an
exercise? Are you mimicking something that's common practice in
another language?

-Mat

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

NAYAK wrote:
> A), there would be an overhead of adding a large number of wrapper
> methods
> for members of classes B and C.

I haven't had time to think through it completely, but what if you
overrode method_missing in A? Your method_missing could find out if
B.responds_to? the message, and if so, send() it the message along with
the original arguments.

The delegation is not a problem, though an elegant way to do it might
require some skills.
The real problem is requirement 2) of the OP, instanciation of class B
shall only be possible in class A, e.g. in an instance of A, I do not think
this is possible, but I would not bet on it (not much).
It would already be nice to have some code which defends against the vanilla
instanciation of B outside of an A instance.
I did not yet come up with such a solution though.
Any ideas?

Cheers
Robert

Just a thought.

···

On 6/20/06, Jeff Cohen <cohen.jeff@gmail.com> wrote:

Jeff
softiesonrails.com

--
Posted via http://www.ruby-forum.com/\.

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

SNIP

Fortunately I did not bet, OP does this pattern fit your needs?

class A
    @@b = Class.new {
        def initialize name; @name=name; end
        def to_s; "#{@name}:#{self.class}"; end
    }

    class << self
        def factory( name );
            @@b.new( name )
        end
    end
end

x = A.factory( "hi" )
puts x

Hope this helps

Cheers
Robert

I don't think it's possible without redefining instance_eval and
class_eval. You could make B an anonymous class assigned to a class
variable, though. That at least provides security through obscurity.

···

On 6/21/06, Robert Dober <robert.dober@gmail.com> wrote:

On 6/20/06, Jeff Cohen <cohen.jeff@gmail.com> wrote:
>
> NAYAK wrote:
> > A), there would be an overhead of adding a large number of wrapper
> > methods
> > for members of classes B and C.
>
> I haven't had time to think through it completely, but what if you
> overrode method_missing in A? Your method_missing could find out if
> B.responds_to? the message, and if so, send() it the message along with
> the original arguments.

The delegation is not a problem, though an elegant way to do it might
require some skills.
The real problem is requirement 2) of the OP, instanciation of class B
shall only be possible in class A, e.g. in an instance of A, I do not think
this is possible, but I would not bet on it (not much).
It would already be nice to have some code which defends against the vanilla
instanciation of B outside of an A instance.
I did not yet come up with such a solution though.
Any ideas?

Cheers
Robert

Just a thought.
>
> Jeff
> softiesonrails.com
>
> --
> Posted via http://www.ruby-forum.com/\.
>

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

--
- Simen

One way would be to make B.new protected/private (similar to the way
it's done in the Singleton mixin). But once you've done that, I'm not
sure if there's a clean way to allow A to use that method -- Ruby
doesn't have "friends" ala C++ (and I'm glad for it). Of course, once
it's protected you *could* have A use send explicitly:

  class B
    class << self
      protected :new
    end
  end

  class A
    def create_b
      @b_objs << B.send(:new)
    end
  end

  a = A.new
  a.create_b # works fine
  B.new # raises NoMethodError

This works, but it doesn't feel very clean :confused:

Jacob Fugal

···

On 6/20/06, Robert Dober <robert.dober@gmail.com> wrote:

The real problem is requirement 2) of the OP, instanciation of class B
shall only be possible in class A, e.g. in an instance of A, I do not think
this is possible, but I would not bet on it (not much).
It would already be nice to have some code which defends against the vanilla
instanciation of B outside of an A instance.
I did not yet come up with such a solution though.
Any ideas?

Why not just make B an anonymous class:

class A
   def initialize
     @bclass = Class.new do
       # class definition here
     end
     @bs =
   end

   def another_b_please
      @bs << @bclass.new
      @bs.last
   end
end

Gary Wright

···

On Jun 20, 2006, at 6:02 PM, Robert Dober wrote:

The real problem is requirement 2) of the OP, instanciation of class B
shall only be possible in class A, e.g. in an instance of A, I do not think
this is possible, but I would not bet on it (not much).

> The real problem is requirement 2) of the OP, instanciation of class B
> shall only be possible in class A, e.g. in an instance of A, I do not
think
> this is possible, but I would not bet on it (not much).
> It would already be nice to have some code which defends against the
vanilla
> instanciation of B outside of an A instance.
> I did not yet come up with such a solution though.
> Any ideas?

One way would be to make B.new protected/private (similar to the way
it's done in the Singleton mixin). But once you've done that, I'm not
sure if there's a clean way to allow A to use that method -- Ruby
doesn't have "friends" ala C++ (and I'm glad for it). Of course, once
it's protected you *could* have A use send explicitly:

as can anyone else :frowning:

  class B

    class << self
      protected :new
    end
  end

  class A
    def create_b
      @b_objs << B.send(:new)
    end
  end

  a = A.new
  a.create_b # works fine
  B.new # raises NoMethodError

B.send(:new) works
But I reasoned along the same lines as you, eventually I came up with an
anonymous class for B inside A
see my next post please.
If that pleases the OP I do not think the anonymous class is easily
accessible, of course one can always create an accessor to the anonymous
class inside A, :frowning:

Cheers
Robert

This works, but it doesn't feel very clean :confused:

···

On 6/21/06, Jacob Fugal <lukfugl@gmail.com> wrote:

On 6/20/06, Robert Dober <robert.dober@gmail.com> wrote:

Jacob Fugal

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

> The real problem is requirement 2) of the OP, instanciation of
> class B
> shall only be possible in class A, e.g. in an instance of A, I do
> not think
> this is possible, but I would not bet on it (not much).

Why not just make B an anonymous class:

class A
   def initialize
     @bclass = Class.new do
       # class definition here
     end
     @bs =
   end

   def another_b_please
      @bs << @bclass.new
      @bs.last
   end
end

Gary that is what I did, and discussed above. ( I used an anonymous class
inside A, you use one inside an instance of A, which might be quite
disturbing unless A is a singleton itself!!)

One can create an accessor to @b at any time

class A
   attr_accessor :bclass
end
A.new.bclass.new #voilà

cheers
Robert

···

On 6/21/06, gwtmp01@mac.com <gwtmp01@mac.com> wrote:

On Jun 20, 2006, at 6:02 PM, Robert Dober wrote:

Gary Wright

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

> One way would be to make B.new protected/private (similar to the way
> it's done in the Singleton mixin). But once you've done that, I'm not
> sure if there's a clean way to allow A to use that method -- Ruby
> doesn't have "friends" ala C++ (and I'm glad for it). Of course, once
> it's protected you *could* have A use send explicitly:

as can anyone else :frowning:

<snip>

If that pleases the OP I do not think the anonymous class is easily
accessible, of course one can always create an accessor to the anonymous
class inside A, :frowning:

Exactly. With a language like Ruby, it's *really* hard to not let
someone do something. I simply went for removing the obvious path, but
not making it impossible.

Jacob Fugal

···

On 6/20/06, Robert Dober <robert.dober@gmail.com> wrote:

On 6/21/06, Jacob Fugal <lukfugl@gmail.com> wrote:

Yeah, I shouldn't have written it as creating a new class for each instance of A. Something like:

class A
   @bclass = Class.new {
     # anonymous class def here
   }
   # details left for the reader...
end

would be better. Yes, you can always reopen A to create an accessor to @bclass but that is a general characteristic of any Ruby code. I think tucking the reference to the class in an instance variable hides it a 'little' better than having the reference be a constant in A. A::B.new is pretty accessible as is changing the visibility of B.new.

Still, I'm not sure that it makes sense to go to all the trouble to 'hide' these other classes. Whenever I see this sort of thing I say 'why bother?'. The idea that you can programatically protect yourself against some hostile coder who can modify the *source* code (or link into your library in a static language) just seems like a waste of time. And the idea that you can enforce correct calls to your API in the absence of some appropriate documentation seems even more far fetched. People don't just guess randomly at the arguments and sequence of calls to a class/library. They are looking at examples or documentation. If they want to experiment with calls that are undocumented or that explicitly violate a documented pre-condition of the API, why do I care?

If you really want to protect yourself against hostile client code, I think you have to go to an inter-process communication interface to your library/service.

Gary Wright

···

On Jun 21, 2006, at 12:51 PM, Robert Dober wrote:

On 6/21/06, gwtmp01@mac.com <gwtmp01@mac.com> wrote:

On Jun 20, 2006, at 6:02 PM, Robert Dober wrote:
> The real problem is requirement 2) of the OP, instanciation of
> class B
> shall only be possible in class A, e.g. in an instance of A, I do
> not think
> this is possible, but I would not bet on it (not much).

Why not just make B an anonymous class:

class A
   def initialize
     @bclass = Class.new do
       # class definition here
     end
     @bs =
   end

   def another_b_please
      @bs << @bclass.new
      @bs.last
   end
end

Gary that is what I did, and discussed above. ( I used an anonymous class
inside A, you use one inside an instance of A, which might be quite
disturbing unless A is a singleton itself!!)

One can create an accessor to @b at any time

class A
  attr_accessor :bclass
end
A.new.bclass.new #voilà

In no language private/protected (or final) is a fool proof security
measure. It is there to provide some safety nets against errors, and
to help design, not for security. It is quite easy in C++ to get at
any function in memory via pointers. In Java people can use AOP to
accomplish this.

Your most economical bet is to just document the class (or whatever)
to be "private, not to be used directly" in Ruby. Sometimes the
low-tech effort is simply the best, especially if any high-tech effort
is going to put *you* to much more troubles than the attacker, who will
circumvent it fast any way.

Jürgen

···

On Wed, Jun 21, 2006 at 08:48:38AM +0900, Jacob Fugal wrote:

On 6/20/06, Robert Dober <robert.dober@gmail.com> wrote:
>On 6/21/06, Jacob Fugal <lukfugl@gmail.com> wrote:
>> One way would be to make B.new protected/private (similar to the way
>> it's done in the Singleton mixin). But once you've done that, I'm not
>> sure if there's a clean way to allow A to use that method -- Ruby
>> doesn't have "friends" ala C++ (and I'm glad for it). Of course, once
>> it's protected you *could* have A use send explicitly:
>
>as can anyone else :frowning:

<snip>

>If that pleases the OP I do not think the anonymous class is easily
>accessible, of course one can always create an accessor to the anonymous
>class inside A, :frowning:

Exactly. With a language like Ruby, it's *really* hard to not let
someone do something. I simply went for removing the obvious path, but
not making it impossible.

Jacob Fugal

--
The box said it requires Windows 95 or better so I installed Linux

gwtmp01@mac.com schrieb:

> The real problem is requirement 2) of the OP, instanciation of
> class B
> shall only be possible in class A, e.g. in an instance of A, I do
> not think
> this is possible, but I would not bet on it (not much).

Why not just make B an anonymous class:

class A
   def initialize
     @bclass = Class.new do
       # class definition here
     end
     @bs =
   end

   def another_b_please
      @bs << @bclass.new
      @bs.last
   end
end

Gary that is what I did, and discussed above. ( I used an anonymous class
inside A, you use one inside an instance of A, which might be quite
disturbing unless A is a singleton itself!!)

One can create an accessor to @b at any time

class A
  attr_accessor :bclass
end
A.new.bclass.new #voilà

Yeah, I shouldn't have written it as creating a new class for each instance of A. Something like:

class A
  @bclass = Class.new {
    # anonymous class def here
  }
  # details left for the reader...
end

would be better. Yes, you can always reopen A to create an accessor to @bclass but that is a general characteristic of any Ruby code. I think tucking the reference to the class in an instance variable hides it a 'little' better than having the reference be a constant in A. A::B.new is pretty accessible as is changing the visibility of B.new.

Still, I'm not sure that it makes sense to go to all the trouble to 'hide' these other classes. Whenever I see this sort of thing I say 'why bother?'. The idea that you can programatically protect yourself against some hostile coder who can modify the *source* code (or link into your library in a static language) just seems like a waste of time. And the idea that you can enforce correct calls to your API in the absence of some appropriate documentation seems even more far fetched. People don't just guess randomly at the arguments and sequence of calls to a class/library. They are looking at examples or documentation. If they want to experiment with calls that are undocumented or that explicitly violate a documented pre-condition of the API, why do I care?

If you really want to protect yourself against hostile client code, I think you have to go to an inter-process communication interface to your library/service.

Gary Wright

I agree...

I think it's kind of old fashioned to hide all and everything from hostile coders doing development in your team (sounds strange anyway...)

My experience is that hiding stuff causes problems when you try to extend existing object / classes. You then have to break everything just
to get your thing going. Even the best gurus oversee possible uses of their libraries...

Hiding methods, etc. never in my career saved me from doing the wrong thing. The only thing that does is good documentation (rare thing!) and talkative names...

···

On Jun 21, 2006, at 12:51 PM, Robert Dober wrote:

On 6/21/06, gwtmp01@mac.com <gwtmp01@mac.com> wrote:

On Jun 20, 2006, at 6:02 PM, Robert Dober wrote:

gwtmp01@mac.com wrote:

...

One can create an accessor to @b at any time

class A
  attr_accessor :bclass
end
A.new.bclass.new #voilà

Yeah, I shouldn't have written it as creating a new class for each
instance of A. Something like:

class A
  @bclass = Class.new {
    # anonymous class def here
  }
  # details left for the reader...
end

would be better. Yes, you can always reopen A to create an accessor to
@bclass but that is a general characteristic of any Ruby code. I think
tucking the reference to the class in an instance variable hides it a
'little' better than having the reference be a constant in A. A::B.new
is pretty accessible as is changing the visibility of B.new.

You can hide it a bit better using a closure, and then attr_accessor
won't expose it. (Sorry if someone suggested this already...I haven't
been following closely.)

class A
  class << self
    bclass = Class.new do
      def foo; puts "foo in bclass"; end
    end

    define_method :new do |*args|
      bclass.new(*args)
    end
  end
end

A.new.foo # ==> foo in bclass

···

On Jun 21, 2006, at 12:51 PM, Robert Dober wrote:

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

<snip>

In no language private/protected (or final) is a fool proof security

I doubt this strongly, Ada springs into mind.

measure. It is there to provide some safety nets against errors, and

to help design, not for security. It is quite easy in C++ to get at
any function in memory via pointers. In Java people can use AOP to
accomplish this.

In theory I hate it, in practice it is frequently sufficent.
Ruby is not doing that bad either, in practice I will often not care if
somebody redefines the access rights of my methods, I feel that this is a
theoretical discussion, though, right ?

Your most economical bet is to just document the class (or whatever)

to be "private, not to be used directly" in Ruby. Sometimes the
low-tech effort is simply the best, especially if any high-tech effort
is going to put *you* to much more troubles than the attacker, who will
circumvent it fast any way.

I appreciate your defence of ruby :wink: but the ability to completely hide
implementation from the interface user is a feature not a bug.

It does not seem a good idea to me to allow everything with the perfect
excuse of following the "enabeling approach", because it does not allow me
to implement some of the more basic principles of modern Software Design
(Data Hiding for instance).

All this is on a philosophical base, in practice Ruby gives me what *I* need
However, *I* is not the world, as has been pointed out to me frequently and
recently, quite a rude message BTW :wink:

Cheers
Robert

Jürgen

···

On 6/21/06, Juergen Strobel <strobel@secure.at> wrote:

--
The box said it requires Windows 95 or better so I installed Linux

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)

iQEVAwUBRJkUEvy64gyiEfXtAQJVyggAzUIlE6uw8LQ7FwWRH2wKucx3qcdi0I5P
KjEJK4a+i01w6ZxUFanxPvCIdlFmwIqz4OLEyV7pRYeKkTOxsaBhc8eS0BWtgNhG
tlrbkG0eXroEYvJnfNGkHAk4UEP11CA/gy6cSzioHRxHtQo8Gt5ktf+uThhHn7+Z
ybSJoMNRltsK/UXc4nxQgw9g8YkNVWooo6QWYf+oqyuNenpE8NoHz5u52CrUUzx0
AoKjR9EVjZeucV5HgmF2Mgfe039A68esCSZ4Xi/3DU1rTfqlIKOaxhDrreBvgoZv
ETANSNrWAX1TBe1Q/jua11nA/3tS2E/8O6oho7NJIeiAiThb20+aOQ==
=G/Vr
-----END PGP SIGNATURE-----

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

I think you rather meant:

  class A
    def initialize
      @b_objs =
    end

    bclass = Class.new do
      def initialize
        puts "creating an instance of bclass"
      end
    end

    define_method :gimme_another_b do |*args|
      @b_objs << bclass.new(*args)
    end
  end

  a = A.new
  a.gimme_another_b # ==> creating an instance of bclass

It looks to me that as long as there is no access to @b_objs, this
successfully hides bclass. But as soon as @b_objs is accessible:

  class A
    attr_reader :b_objs
  end
  bclass = a.b_objs.first.class
  bclass.new # ==> creating an instance of bclass

Not meant to be nitpicking you specifically Joel, just continuing to
demonstrate that one *really* can't prevent things like this in a
language with open and first-class Classes. :slight_smile:

Jacob Fugal

···

On 6/21/06, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

You can hide it a bit better using a closure, and then attr_accessor
won't expose it. (Sorry if someone suggested this already...I haven't
been following closely.)

class A
  class << self
    bclass = Class.new do
      def foo; puts "foo in bclass"; end
    end

    define_method :new do |*args|
      bclass.new(*args)
    end
  end
end

A.new.foo # ==> foo in bclass

Jacob Fugal wrote:

class A
   def initialize
     @b_objs =
   end

   bclass = Class.new do
     def initialize
       puts "creating an instance of bclass"
     end
   end

   define_method :gimme_another_b do |*args|
     @b_objs << bclass.new(*args)
   end
end

a = A.new
a.gimme_another_b # ==> creating an instance of bclass

It looks to me that as long as there is no access to @b_objs, this
successfully hides bclass. But as soon as @b_objs is accessible:

class A
   attr_reader :b_objs
end
bclass = a.b_objs.first.class
bclass.new # ==> creating an instance of bclass

We can just keep playing the closure game:

  class A
    def initialize
      class << self
        b_objs =

        bclass = Class.new do
          def initialize
            puts "creating an instance of bclass"
          end
        end

        define_method :gimme_another_b do |*args|
          b = bclass.new(*args)
          b_objs << b
          b # return b instead of b_objs
        end

        define_method :secret_method_to_get_b_objs do
          b_objs
        end
      end
    end
  end

  a = A.new
  p a.secret_method_to_get_b_objs
  p a.gimme_another_b
  p a.secret_method_to_get_b_objs

__END__

output:


creating an instance of bclass
#<#<Class:0xb7dc4aa0>:0xb7dc453c>
[#<#<Class:0xb7dc4aa0>:0xb7dc453c>]

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407