Inner Class Relationship

  • Thread starter James Edward Gray II
  • Start date
J

James Edward Gray II

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
 
T

trans. (T. Onoma)

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.
 
J

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.)

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
 
F

Francis Hwang

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.


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://fhwang.net/
 
J

James Edward Gray II

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

trans. (T. Onoma)

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.
 
C

Carlos

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>
 
F

Francis Hwang

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://fhwang.net/
 
A

Abraham Vionas

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
 
J

James Britt

Abraham said:
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

trans. (T. Onoma)

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?name=access

--
( o _ カラãƒ
// trans.
/ \ (e-mail address removed)

[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').chr}
-Tadayoshi Funaba
 
G

Gennady Bystritsky

How about something like this:

class Outer
class Inner
def initialize(&block)
@cleaner = block
end

def close
@cleaner.call self
end
end

def create_inner
inner = Inner.new { |_inner|
remove_inner(_inner)
}
...
end

private
#######
def remove_inner
...
end
end

Sincerely,
Gennady Bystritsky
 
A

Abraham Vionas

Sure!

It is:

rails Todo

So including the path: C:\cs\www>rails Todo



-----Original Message-----
From: James Britt [mailto:[email protected]]
Sent: Saturday, November 20, 2004 7:40 PM
To: ruby-talk ML
Subject: Re: Error trying to get going with Rails Todo tutorial...

Abraham said:
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
 
Z

Zach Dennis

Francis said:
[snip]

Also, have you considered using Observable?

I have to go with Francis's suggestion on this. Using Observable to
implement the Observer pattern sounds almost like a hand/glove fitting
for your problem.

Zach
 
N

Neil Stevens

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.

class Inner
attr_accessor :callback

def initialize
@callback = do
#nothing
end
end

def somethingHappens
@callback.call
end
end

class Outer
def initialize
@inner = Inner.new
@inner.callback = do
# something that is totally internal
end
end
end
 
N

Neil Stevens

class Inner
attr_accessor :callback

def initialize
@callback = do
#nothing
end
end

def somethingHappens
@callback.call
end
end

class Outer
def initialize
@inner = Inner.new
@inner.callback = do
# something that is totally internal
end
end
end

I missed a couple 'Proc.new's in there, but the idea should be clear
enough I hope.
 
J

James Britt

Abraham said:
Sure!

It is:

rails Todo

So including the path: C:\cs\www>rails Todo

Well, that seems pretty straightforward ...

I tried it on my Win2K box, and half-expected the capitalized name to
cause a problem, but all the directories and code is created without
any errors that I can see.

I'm using rake and rails installed via rubygems, all recently updated.

Maybe someone else knows the problem?

James
 
J

James Edward Gray II

Francis said:
[snip]
Also, have you considered using Observable?

I have to go with Francis's suggestion on this. Using Observable to
implement the Observer pattern sounds almost like a hand/glove fitting
for your problem.

It has the exact same flaw actually, update() must be public.

My thanks to all though. You did give me what I need (multiple
options!) and I'm grateful.

James Edward Gray II
 
J

James Edward Gray II

But then, what do we mean by private? What if you just hid the method
in the RDoc?

This is a good point. I learned my OO in Java, so I'm naturally
paranoid. What you suggest here is probably the most "Ruby" solution
and would serve fine. Violate the documentation and all bets are off
anyway, right?

I am trying to be more open. I'm warming to Duck Typing, slowly but
surely. Please be patient with us paranoid people and kindly refocus
us when we're going overboard.

Thanks.

James Edward Gray II
 
A

Abraham Vionas

I'm almost afraid to ask but could the fact that I'm using Ruby 1.9 cause
this problem? And if so is reinstalling 1.8.3 a simple matter of just
unzipping/overwriting my current directories, etc?

One more thought... I have two separate installations of Rails. The active
installation is at --> C:\cs\www\rails\ ...the non-active installation is at
--> C:\cs\ruby\rails

When I modified the header files (replaced the #!/usr/local/bin (or whatever
it is) with my C: path --> C:\cs\ruby\bin) that wouldn't cause a problem
like this would it?



-----Original Message-----
From: James Britt [mailto:[email protected]]
Sent: Saturday, November 20, 2004 9:13 PM
To: ruby-talk ML
Subject: Re: Error trying to get going with Rails Todo tutorial...

Abraham said:
Sure!

It is:

rails Todo

So including the path: C:\cs\www>rails Todo

Well, that seems pretty straightforward ...

I tried it on my Win2K box, and half-expected the capitalized name to cause
a problem, but all the directories and code is created without any errors
that I can see.

I'm using rake and rails installed via rubygems, all recently updated.

Maybe someone else knows the problem?

James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,161
Messages
2,570,892
Members
47,430
Latest member
7dog123

Latest Threads

Top