[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Inner Class Relationship

James Gray

11/20/2004 10:32:00 PM

I have an inner class that needs to send it's parent object (outer
class) a message when a certain event occurs.

I would rather not create a method in the outer class for this as it is
a messy implementation detail that should be hidden away under lock and
key.

Any suggestions for a clean way to implement this? It's a blind spot
for me.

Thanks.

James Edward Gray II



23 Answers

T. Onoma

11/20/2004 11:01:00 PM

0

On Saturday 20 November 2004 05:31 pm, James Edward Gray II wrote:
| I have an inner class that needs to send it's parent object (outer
| class) a message when a certain event occurs.
|
| I would rather not create a method in the outer class for this as it is
| a messy implementation detail that should be hidden away under lock and
| key.
|
| Any suggestions for a clean way to implement this? It's a blind spot
| for me.
|
| Thanks.
|
| James Edward Gray II

If I understand correctly, try passing self of parent to the the inner object
when it's created.

class Inner
def initialize( parent )
@parent = parent
end
end

class Outer
def initialize
Inner.new(self)
end
end

With any luck, in the future we will have a "caller" method that can refer to
the parent object from Inner#initialize, i.e. without having to specifically
pass self. (Personally I've always thought #object_parent should be built-in
anyway.)

T.



James Gray

11/20/2004 11:11:00 PM

0

On Nov 20, 2004, at 5:01 PM, trans. (T. Onoma) wrote:

> If I understand correctly, try passing self of parent to the the inner
> object
> when it's created.
>
> class Inner
> def initialize( parent )
> @parent = parent
> end
> end
>
> class Outer
> def initialize
> Inner.new(self)
> end
> end
>
> With any luck, in the future we will have a "caller" method that can
> refer to
> the parent object from Inner#initialize, i.e. without having to
> specifically
> pass self. (Personally I've always thought #object_parent should be
> built-in
> anyway.)

I don't know what it is about me and not being able to properly convey
what I mean the first time. :D

What you posted, is more or less what I'm doing. My desire was to find
a way around using a PUBLIC method in the outer class. It's really a
message that only the inner class should be able to send.

James Edward Gray II



Francis Hwang

11/20/2004 11:55:00 PM

0

Since you haven't said much about how you're using this, maybe my
answer will be a little presumptive, but: Is there are a particular
reason you want the inner class to relate to the outer class this way?
When I used inner classes (which is a lot), the relationship between
the two is usually fairly clear: The outer class uses an instance of
the inner class to delegate some small piece of logic, but the inner
class doesn't know much about the outer class as a whole and doesn't
change its state.

Something like:

class Outer
def outer_method
inner = Inner.new
result = inner.inner_method
do_something_based_on result
end

class Inner
def inner_method
end
end
end

It's possible that doing it this way violates Tell Don't Ask, but it
seems to work fine for me.

F.


On Nov 20, 2004, at 5:31 PM, James Edward Gray II wrote:

> I have an inner class that needs to send it's parent object (outer
> class) a message when a certain event occurs.
>
> I would rather not create a method in the outer class for this as it
> is a messy implementation detail that should be hidden away under lock
> and key.
>
> Any suggestions for a clean way to implement this? It's a blind spot
> for me.
>
> Thanks.
>
> James Edward Gray II
>
>
>

Francis Hwang
http://f...



James Gray

11/21/2004 12:22:00 AM

0

On Nov 20, 2004, at 5:55 PM, Francis Hwang wrote:

> Since you haven't said much about how you're using this, maybe my
> answer will be a little presumptive, but: Is there are a particular
> reason you want the inner class to relate to the outer class this way?

Yes.

Even if I separate the two classes, my questions remain unchanged:
What's a good way to allow one type of object to send private-ish
messages to another type of object?

As for details: My outer class is a server. My inner class is a
connection for that server. When a connection ends, I need a way to
notify the Server object to remove it from it's maintenance list.
That's the message I'm wanting to hide from the outside world.

Thanks for the suggestions.

James Edward Gray II



T. Onoma

11/21/2004 12:29:00 AM

0

On Saturday 20 November 2004 06:10 pm, James Edward Gray II wrote:
| On Nov 20, 2004, at 5:01 PM, trans. (T. Onoma) wrote:
| > If I understand correctly, try passing self of parent to the the inner
| > object
| > when it's created.
| >
| > class Inner
| > def initialize( parent )
| > @parent = parent
| > end
| > end
| >
| > class Outer
| > def initialize
| > Inner.new(self)
| > end
| > end
| >
| > With any luck, in the future we will have a "caller" method that can
| > refer to
| > the parent object from Inner#initialize, i.e. without having to
| > specifically
| > pass self. (Personally I've always thought #object_parent should be
| > built-in
| > anyway.)
|
| I don't know what it is about me and not being able to properly convey
| what I mean the first time. :D
|
| What you posted, is more or less what I'm doing. My desire was to find
| a way around using a PUBLIC method in the outer class. It's really a
| message that only the inner class should be able to send.

Making a guess, you're four objects down a hierarchy chain and want to reach
up a few levels? That been my experience, but have never found a better
solution. You still have to have some _reference_ to that outer object
--that's the problem. You might try something like this if you can determine
reasonable keys.

class Outer
def initialize
@@gimme[:akey] = self
end
def self.gimme(key)
@@gimme[key]
end
end

Also you could do what what you're doing now but inversely. Something like:

class Outer
o = Inner.new
(class << o; self; end).send(:define_method, :parent){ self }
end

T.


Carlos

11/21/2004 1:20:00 AM

0

[James Edward Gray II <james@grayproductions.net>, 2004-11-21 01.22 CET]
> Even if I separate the two classes, my questions remain unchanged:
> What's a good way to allow one type of object to send private-ish
> messages to another type of object?
>
> As for details: My outer class is a server. My inner class is a
> connection for that server. When a connection ends, I need a way to
> notify the Server object to remove it from it's maintenance list.
> That's the message I'm wanting to hide from the outside world.

This is a little contrived, and maybe the best option is to just use a
public method.

class Outer
def remove x
puts "removing #{x}"
end
private :remove

def initialize
@exportable_private_methods = {
"remove" => lambda {|x| remove x}
}
end

class Inner
def initialize outer_methods
@outer_methods = outer_methods
end

def run
puts "running"
@outer_methods["remove"].call(self)
end
end

def run
Inner.new(@exportable_private_methods).run
end
end

Outer.new.run

# =>
running
removing #<Outer::Inner:0x402bc2c8>


Francis Hwang

11/21/2004 1:35:00 AM

0


On Nov 20, 2004, at 7:22 PM, James Edward Gray II wrote:

> On Nov 20, 2004, at 5:55 PM, Francis Hwang wrote:
>
>> Since you haven't said much about how you're using this, maybe my
>> answer will be a little presumptive, but: Is there are a particular
>> reason you want the inner class to relate to the outer class this
>> way?
>
> Yes.
>
> Even if I separate the two classes, my questions remain unchanged:
> What's a good way to allow one type of object to send private-ish
> messages to another type of object?
>
> As for details: My outer class is a server. My inner class is a
> connection for that server. When a connection ends, I need a way to
> notify the Server object to remove it from it's maintenance list.
> That's the message I'm wanting to hide from the outside world.
>

Maybe part of the question has to do with the nature of private-ness in
Ruby .... I don't think it's easy in Ruby to have a sort of C++-like
friend relationship, where you privilege certain classes to call
certain methods. (I did something like this in my ContextualService
classes for Lafcadio, by checking caller, but it's sort of a kludge and
I wouldn't necessarily recommend it for general use.)

But then, what do we mean by private? What if you just hid the method
in the RDoc? Do you imagine a situation where people might use it
incorrectly, either by accident or maliciously? This differs depending
on how the code's going to be used, of course.

Also, have you considered using Observable?

Francis Hwang
http://f...



Abraham Vionas

11/21/2004 2:20:00 AM

0

I know this is a retarded problem, but somehow I managed to set things up
such that I get an error when running "Rails Todo". Rather than creating the
directory structure (etc) I just get an error:

C:/cs/ruby/bin/rails:9:in 'system': Exec format error - rake fresh_rpa_rails
(Errno::ENOEXEC)
from C:/cs/ruby/bin/rails:9

Does anyone recognize the above and know what I need to do about it? I
appreciate your help very much!

Regards, Abe



James Britt

11/21/2004 2:40:00 AM

0

Abraham Vionas wrote:
> I know this is a retarded problem, but somehow I managed to set things up
> such that I get an error when running "Rails Todo". Rather than creating the
> directory structure (etc) I just get an error:

Can you post the actual command you are running?

James


T. Onoma

11/21/2004 2:43:00 AM

0

On Saturday 20 November 2004 08:35 pm, Francis Hwang wrote:
| But then, what do we mean by private? What if you just hid the method
| in the RDoc? Do you imagine a situation where people might use it
| incorrectly, either by accident or maliciously? This differs depending
| on how the code's going to be used, of course.

Also, you may be interested in this:

http://raa.ruby-lang.org/list.rhtml?n...

--
( o _ ���
// trans.
/ \ transami@runbox.com

[8,16,20,29,78,65,2,14,26,12,12,28,71,114,12,13,12,82,72,21,17,4,10,2,95].
each_with_index{|x,i| $><<(x^'Begin landing your troops'[i]).chr}
-Tadayoshi Funaba