Conditionally make a method private?

Hello again!

I’ve googled this one, as well as looking in Pickaxe and Ruby Way, and I
can’t seem to find out anything about this. What I want to do is create a
class that, when instanced, depending on the argument given to .new, hides
some methods or others. For example:

class Hider
def initialize(val)
private_class_method :method1 if val
private_class_method :method2 if not val
end

def method1
    #...
end

def method2
    #...
end

end

ahider = Hider.new(true)

This spits back out to me:

3:in initialize': undefined methodprivate_class_method’ for
#Hider:0x401c157c (NameError)
from test.rb:16:in `new’
from test.rb:16

What I want to happen is when I issue “Hider.new(true)”, I want it to make
it so that method1 is private. Likewise, when I do “Hider.new(false)”, I
want it to make method2 private.

I’ve tried putting the private_class_method in other seperate methods, I’ve
tried just using “private :method2” and the like, but they all give me a
similar response. I’m guessing that private and private_class_method can’t
be inside of other methods.

Is conditional hiding of methods like I want to do even possible?

Any insight is appreciated,
Jeremy

Would a Factory pattern work better in this case? I.e. have a base
class, then derive the two different classes from that. Use a Factory to
give you the instance you ask for. If you call
Factory.instance(SOME_NAME) would return a SomeName instance, whereas
Factory.instance(SOME_OTHER_NAME) would return a SomeOtherName instance.
SomeName and SomeOtherName would both be subclasses of BaseClass.

Regards,
JJ

···

On Tue, 2003-03-25 at 21:05, Jeremy wrote:

Hello again!

I’ve googled this one, as well as looking in Pickaxe and Ruby Way, and I
can’t seem to find out anything about this. What I want to do is create a
class that, when instanced, depending on the argument given to .new, hides
some methods or others. For example:
ahider = Hider.new(true)

This spits back out to me:

3:in initialize': undefined method private_class_method’ for
#Hider:0x401c157c (NameError)
from test.rb:16:in `new’
from test.rb:16

What I want to happen is when I issue “Hider.new(true)”, I want it to make
it so that method1 is private. Likewise, when I do “Hider.new(false)”, I
want it to make method2 private.

Jeremy wrote:

Hello again!

I’ve googled this one, as well as looking in Pickaxe and Ruby Way, and I
can’t seem to find out anything about this. What I want to do is create a
class that, when instanced, depending on the argument given to .new, hides
some methods or others. For example:

class Hider
def initialize(val)
private_class_method :method1 if val
private_class_method :method2 if not val
end

def method1
    #...
end

def method2
    #...
end

end

ahider = Hider.new(true)

This spits back out to me:

3:in initialize': undefined method private_class_method’ for
#Hider:0x401c157c (NameError)
from test.rb:16:in `new’
from test.rb:16

What I want to happen is when I issue “Hider.new(true)”, I want it to make
it so that method1 is private. Likewise, when I do “Hider.new(false)”, I
want it to make method2 private.

I’ve tried putting the private_class_method in other seperate methods, I’ve
tried just using “private :method2” and the like, but they all give me a
similar response. I’m guessing that private and private_class_method can’t
be inside of other methods.

They can, but remember that methods such as private are methods on the
Module and Class object instances, not your objects instances. They are
also private.

Is conditional hiding of methods like I want to do even possible?
Any insight is appreciated,
Jeremy

class Hider
def initialize(val)
p self.type
class <<self
private :method1
end if val
class <<self
private :method2
end if not val
end

def method1
    #...
end

def method2
    #...
end

end

ahider = Hider.new(true)
bhider = Hider.new(false)
ahider.method2
bhider.method1

begin
ahider.method1
rescue NameError => err
puts err
end
begin
bhider.method2
rescue NameError => err
puts err
end

···


([ Kent Dahl ]/)_ ~ [ http://www.stud.ntnu.no/~kentda/ ]/~
))_student
/(( _d L b_/ NTNU - graduate engineering - 5. year )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)

John Johnson wrote:

Hello again!

I’ve googled this one, as well as looking in Pickaxe and Ruby Way, and I
can’t seem to find out anything about this. What I want to do is create
a class that, when instanced, depending on the argument given to .new,
hides
some methods or others. For example:
ahider = Hider.new(true)

This spits back out to me:

3:in initialize': undefined method private_class_method’ for
#Hider:0x401c157c (NameError)
from test.rb:16:in `new’
from test.rb:16

What I want to happen is when I issue “Hider.new(true)”, I want it to
make
it so that method1 is private. Likewise, when I do “Hider.new(false)”, I
want it to make method2 private.

Would a Factory pattern work better in this case? I.e. have a base
class, then derive the two different classes from that. Use a Factory to
give you the instance you ask for. If you call
Factory.instance(SOME_NAME) would return a SomeName instance, whereas
Factory.instance(SOME_OTHER_NAME) would return a SomeOtherName instance.
SomeName and SomeOtherName would both be subclasses of BaseClass.

It would indeed work, but I was hoping to be able to keep it down to one
object. Here was something else I had tried:

class Hider

private_class_method :new

def initialize(val1,val2)
    @vartype1 = val1
    @vartype2 = val2
end

def Hider.type1
    new(true,false)
end

def Hider.type2
    new(false,true)
end

def Hider.type3
    new(true,true)
end

def method1
    puts "method 1" if @vartype1
end

def method2
    puts "method 2" if @vartype2
end

end

Then how methods work depends on whether Hider.type1 or Hider.type2 is used.

a = Hider.type1
a.method1
a.method2

gives me:

method 1

While this works as expected, it doesn’t really hide method2. It just
doesn’t execute the specified code if @vartype2 if false. Not quite what I
was hoping for, but it gives a similar effect.

Thanks for your suggestion, though. That was a mighty quick response!

Jeremy

···

On Tue, 2003-03-25 at 21:05, Jeremy wrote:

Kent Dahl wrote:

They can, but remember that methods such as private are methods on the
Module and Class object instances, not your objects instances. They are
also private.

Is conditional hiding of methods like I want to do even possible?
Any insight is appreciated,
Jeremy

class Hider
def initialize(val)
p self.type
class <<self
private :method1
end if val
class <<self
private :method2
end if not val
end

def method1
    #...
end

def method2
    #...
end

end

ahider = Hider.new(true)
bhider = Hider.new(false)
ahider.method2
bhider.method1

begin
ahider.method1
rescue NameError => err
puts err
end
begin
bhider.method2
rescue NameError => err
puts err
end

Ah! I believe I understand. Thank you for this!

Jeremy

John Johnson wrote:

Hello again!

I’ve googled this one, as well as looking in Pickaxe and Ruby Way, and I
can’t seem to find out anything about this. What I want to do is create
a class that, when instanced, depending on the argument given to .new,
hides
some methods or others. For example:
ahider = Hider.new(true)

This spits back out to me:

3:in initialize': undefined method private_class_method’ for
#Hider:0x401c157c (NameError)
from test.rb:16:in `new’
from test.rb:16

What I want to happen is when I issue “Hider.new(true)”, I want it to
make
it so that method1 is private. Likewise, when I do “Hider.new(false)”, I
want it to make method2 private.

Would a Factory pattern work better in this case? I.e. have a base
class, then derive the two different classes from that. Use a Factory to
give you the instance you ask for. If you call
Factory.instance(SOME_NAME) would return a SomeName instance, whereas
Factory.instance(SOME_OTHER_NAME) would return a SomeOtherName instance.
SomeName and SomeOtherName would both be subclasses of BaseClass.

It would indeed work, but I was hoping to be able to keep it down to one
object. Here was something else I had tried:

class Hider

method 1

While this works as expected, it doesn’t really hide method2. It just
doesn’t execute the specified code if @vartype2 if false. Not quite what I
was hoping for, but it gives a similar effect.

You must also consider the maintainability of the code. I’m sure you
have a good reason for wanting it to be one class, but does that
outweigh being able to understand how it works when you come back to it
next year? Or next month, in my case :slight_smile:

Thanks for your suggestion, though. That was a mighty quick response!

You’re welcome!

Regards,
JJ

···

On Tue, 2003-03-25 at 21:45, Jeremy wrote:

On Tue, 2003-03-25 at 21:05, Jeremy wrote:

Now that you know how to do it, are you sure that’s what you really
want to do? :wink:

Reading your previous postings I found the following:

“Perhaps there are other ideas for what I want I’m trying to accomplish
in the long run. I wanted a simple way to have two (or more) completely
unrelated classes to send messages back and forth without having to
even know about each other. I wanted something that would interfere
the least with each class.”

Now this really sounds like the Databus.

More info can be found at
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/64694

···

On Thu, Mar 27, 2003 at 10:30:36AM +0900, Jeremy wrote:

Ah! I believe I understand. Thank you for this!


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

…Deep Hack Mode – that mysterious and frightening state of
consciousness where Mortal Users fear to tread.
– Matt Welsh

John Johnson wrote:

Would a Factory pattern work better in this case? I.e. have a base
class, then derive the two different classes from that. Use a Factory
to give you the instance you ask for. If you call
Factory.instance(SOME_NAME) would return a SomeName instance, whereas
Factory.instance(SOME_OTHER_NAME) would return a SomeOtherName
instance. SomeName and SomeOtherName would both be subclasses of
BaseClass.

It would indeed work, but I was hoping to be able to keep it down to one
object. Here was something else I had tried:

class Hider

method 1

While this works as expected, it doesn’t really hide method2. It just
doesn’t execute the specified code if @vartype2 if false. Not quite what
I was hoping for, but it gives a similar effect.

You must also consider the maintainability of the code. I’m sure you
have a good reason for wanting it to be one class, but does that
outweigh being able to understand how it works when you come back to it
next year? Or next month, in my case :slight_smile:

I understand what you mean. I think I was trying too hard to conserve
memory/space. I guess I thought that if I had one class that behaved in
such a way, it might be easier to maintain, but I can see where if I run
into getting a lot of methods in there, that determining which ones run for
one instance and which ones run for another would get kind of tough.

Perhaps there are other ideas for what I want I’m trying to accomplish in
the long run. I wanted a simple way to have two (or more) completely
unrelated classes to send messages back and forth without having to even
know about each other. I wanted something that would interfere the least
with each class. The reason why I wanted to have the private methods to be
able to change on assignment was because I wanted some classes to only send
messages, some to only receive messages, and others that could do both.
For now, I finally settled on this little bit of code:

module Status_messenger
class Status
def Status.set(val)
@@status = val
end

    def Status.get
        @@status
    end
end

def status=(val)
    Status.set val
end

def status
    Status.get
end

end

This way, all I have to do is “include Status_messenger” in a class, and now
it can communicate with any other classes that have been “enabled” as well.
I settled on a seperate class inside the module because I didn’t want extra
class attributes to be created within each class. I wanted it to interfere
as little as possible with everything else. Unfortunately it doesn’t allow
for some classes to send-only or receive-only, but for my small purpose,
it’s not an issue right now. Perhaps I’ll work on it further one day.

Bah, I’m rambling… sorry. I’ll go now.

Thanks again for your help and suggestions!

Jeremy

Hi –

For now, I finally settled on this little bit of code:

module Status_messenger
class Status
def Status.set(val)
@@status = val
end

    def Status.get
        @@status
    end
end

def status=(val)
    Status.set val
end

def status
    Status.get
end

end

Don’t forget that the class variable @@status will be shared by any
and all that have access to it. In the following example, note that
M1’s view of status changes when M2 changes it:

class M1
include Status_messenger
Status.set(true)
puts Status.get # true
end

class M2
include Status_messenger
Status.set(false)
end

class M1
puts Status.get # false
end

Assuming I’m right that this isn’t what you want, you might be better
off with class instance variables:

class Status
class << self; attr_accessor :status
end

or something in that family.

David

···

On Wed, 26 Mar 2003, Jeremy wrote:


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

dblack@superlink.net wrote:

Hi –

For now, I finally settled on this little bit of code:

module Status_messenger
class Status
def Status.set(val)
@@status = val
end

    def Status.get
        @@status
    end
end

def status=(val)
    Status.set val
end

def status
    Status.get
end

end

Don’t forget that the class variable @@status will be shared by any
and all that have access to it. In the following example, note that
M1’s view of status changes when M2 changes it:

class M1
include Status_messenger
Status.set(true)
puts Status.get # true
end

class M2
include Status_messenger
Status.set(false)
end

class M1
puts Status.get # false
end

Assuming I’m right that this isn’t what you want, you might be better
off with class instance variables:

class Status
class << self; attr_accessor :status
end

or something in that family.

Actually, if I understand what you are saying, this is EXACTLY what I want.
What I was trying to accomplish was having an attribute that wasn’t quite
global, but more accessable than just a normal class attribute. I do want
M1’s view of the status to change when I change it in M2. I think that the
best way to think of it is like this:

I have two classes (a database class, and a menu class) that are different
enough that it doesn’t warrant doing inheritance from a single superclass,
but I need any instances of the two classes to communicate directly. I
didn’t really want to muck up global space with an attribute, because I
don’t want all things to be able to access it. But I also didn’t want to
do a lot of hardcoding in each class to make them “aware” of each other. I
wanted this to kind of act like a community whiteboard. Also, I needed
something that could possibly “do more”, such as formatting, or automatic
message clearing, or things like that. Using the above code was about the
best that I could come up with for such a beast. As stated in the message
to John Johnson, the reasoning for the original posting was to see if I
could have some of them to act only as senders of messages (the databases),
and some as readers of messages (the menus). I still would like to do
something like that, but that will take a bit more thinking for me yet.
I’m still fresh meat in the ruby community, only having been using it for
about 3 weeks now.

If I’ve described something that is already existing in the ruby language,
of if you have any suggestions or pointers for what I’ve said, I’d be glad
to hear them.

Thanks for the response!

Jeremy

···

On Wed, 26 Mar 2003, Jeremy wrote:

Actually, if I understand what you are saying, this is EXACTLY what I want.
What I was trying to accomplish was having an attribute that wasn’t quite
global, but more accessable than just a normal class attribute. I do want

But in a way it is global, as there’s only one class attribute, it is
simply scoped into that class. Every pair of database/menu objects will
be using the same attribute.

If all you want is to share some part of the internal state, you can simply
externalize it as a separate object and keep as many references as needed.

M1’s view of the status to change when I change it in M2. I think that the
best way to think of it is like this:

I have two classes (a database class, and a menu class) that are different
enough that it doesn’t warrant doing inheritance from a single superclass,
but I need any instances of the two classes to communicate directly. I
didn’t really want to muck up global space with an attribute, because I
don’t want all things to be able to access it. But I also didn’t want to
do a lot of hardcoding in each class to make them “aware” of each other. I
wanted this to kind of act like a community whiteboard. Also, I needed
something that could possibly “do more”, such as formatting, or automatic
message clearing, or things like that. Using the above code was about the
best that I could come up with for such a beast. As stated in the message
to John Johnson, the reasoning for the original posting was to see if I
could have some of them to act only as senders of messages (the databases),
and some as readers of messages (the menus). I still would like to do
something like that, but that will take a bit more thinking for me yet.
I’m still fresh meat in the ruby community, only having been using it for
about 3 weeks now.

Now all this about writers and readers reminds me the Databus being used
by Freeride. In believe it probably what you want (esp. the “act like a
community whiteboard” part :slight_smile:

"The FreeBASE Databus is the internal mechanism through which plugins
communicate with each other. It is a hierarchical publish/subscribe
system that combines the features of a data repository and a messaging
system.

[…]

The Databus uses a publish/subscribe mechanism that allows you to use
the Databus as a messaging system. You can subscribe to any slot in the
Databus to receive notifications whenever that slot changes."

···

On Thu, Mar 27, 2003 at 10:50:44AM +0900, Jeremy wrote:

dblack@superlink.net wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

People are going to scream bloody murder about that.
– Seen on linux-kernel

Mauricio Fernández wrote:

Actually, if I understand what you are saying, this is EXACTLY what I
want. What I was trying to accomplish was having an attribute that wasn’t
quite
global, but more accessable than just a normal class attribute. I do
want

But in a way it is global, as there’s only one class attribute, it is
simply scoped into that class. Every pair of database/menu objects will
be using the same attribute.

True. And that’s pretty much what I need. One to be shared among all, (as
opposed to each pair sharing their own) but only among all specified
objects. There are other objects, such as books, teachers, and such, that
do not (and should not) need access to this. Also, this was a simplified
example. Yes, here I did have just one class attribute in use, but in
actuality, there are several in use that are all being processed in one way
or another.

If all you want is to share some part of the internal state, you can
simply externalize it as a separate object and keep as many references as
needed.

Externalize? I’m not sure exactly how you mean this. Are you talking about
releasing the information as some global object? Or am I just way off
here…?

M1’s view of the status to change when I change it in M2. I think that
the best way to think of it is like this:

I have two classes (a database class, and a menu class) that are
different enough that it doesn’t warrant doing inheritance from a single
superclass,
but I need any instances of the two classes to communicate directly. I
didn’t really want to muck up global space with an attribute, because I
don’t want all things to be able to access it. But I also didn’t want to
do a lot of hardcoding in each class to make them “aware” of each other.
I
wanted this to kind of act like a community whiteboard. Also, I needed
something that could possibly “do more”, such as formatting, or automatic
message clearing, or things like that. Using the above code was about
the
best that I could come up with for such a beast. As stated in the
message to John Johnson, the reasoning for the original posting was to
see if I could have some of them to act only as senders of messages (the
databases),
and some as readers of messages (the menus). I still would like to do
something like that, but that will take a bit more thinking for me yet.
I’m still fresh meat in the ruby community, only having been using it for
about 3 weeks now.

Now all this about writers and readers reminds me the Databus being used
by Freeride. In believe it probably what you want (esp. the “act like a
community whiteboard” part :slight_smile:

rubyide.org

"The FreeBASE Databus is the internal mechanism through which plugins
communicate with each other. It is a hierarchical publish/subscribe
system that combines the features of a data repository and a messaging
system.

[…]

The Databus uses a publish/subscribe mechanism that allows you to use
the Databus as a messaging system. You can subscribe to any slot in the
Databus to receive notifications whenever that slot changes."

Wow. Good stuff. I think it’s a bit more complicated than what I need, but
I’ll take a closer look at it. Thanks for the info.

Jeremy

···

On Thu, Mar 27, 2003 at 10:50:44AM +0900, Jeremy wrote:

dblack@superlink.net wrote:

Just that :slight_smile:
One last thing though: you should probably pass references around
instead of simply using a global (even if they all come from, say,
GlobalState.instance), for this way you’ll be able to change associations
easily in the future…

ie.

class Foo
def initialize( … state )
@state = state
end
def foo
#use @state
end
end

instead of “hardwiring”
class Foo

def foo
#use $state
end
end

···

On Fri, Mar 28, 2003 at 11:35:56AM +0900, Jeremy wrote:

Mauricio Fernández wrote:

On Thu, Mar 27, 2003 at 10:50:44AM +0900, Jeremy wrote:

dblack@superlink.net wrote:
Actually, if I understand what you are saying, this is EXACTLY what I
want. What I was trying to accomplish was having an attribute that wasn’t
quite
global, but more accessable than just a normal class attribute. I do
want

But in a way it is global, as there’s only one class attribute, it is
simply scoped into that class. Every pair of database/menu objects will
be using the same attribute.

True. And that’s pretty much what I need. One to be shared among all, (as
opposed to each pair sharing their own) but only among all specified
objects. There are other objects, such as books, teachers, and such, that
do not (and should not) need access to this. Also, this was a simplified
example. Yes, here I did have just one class attribute in use, but in
actuality, there are several in use that are all being processed in one way
or another.

If all you want is to share some part of the internal state, you can
simply externalize it as a separate object and keep as many references as
needed.

Externalize? I’m not sure exactly how you mean this. Are you talking about
releasing the information as some global object? Or am I just way off
here…?


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Sex dumps core
(Sex is a Simple editor for X11)
– Seen on debian bugtracking