Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Making object methods available externally

Reply
Thread Tools

Making object methods available externally

 
 
David Stanford
Guest
Posts: n/a
 
      02-04-2009
Hi all,

I'm having trouble figuring out a way of creating a method within a
class that's available not only to the other object methods (object
instances), but also externally, as if I were to use 'self.method'.
Below is an (admittedly, lame) example of what I'm referring to:

#############################

class CheesePhrase
def initialize(phrase)
@phrase = phrase
say_it
end

def say_it(phrase=@phrase)
puts "#{phrase}"
end
end

#############################

The above code works fine if I create an object instance, and (if I
choose to do so) call the method 'say_it', like so:

some_cheese_phrase = CheesePhrase.new("I like cheese.")
some_cheese_phrase.say_it

However, what if I'd also like to call the method directly, without
creating a new instance? For example, simply with:

CheesePhrase.say_it("I like cheese, too.")

I can't do this without using 'self.say_it' in the method declaration.
Though, if I do that, I am no longer able to call the method in
'initialize' since 'self.say_it' is now a class method. I get the
following error:

NoMethodError: undefined method `say_it' for #<CheesePhrase:0x284372f4
@phrase="I like cheese">
from (irb):4:in `initialize'
from (irb):11:in `new'

I'm sure I must be doing something wrong, or my concept of how to
implement this is totally wrong. The only other thought I've had is to
create duplicate methods, but this seems to violate the famed DRY
principle. Any advice would be much appreciated.

Thanks in advance!

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

 
Reply With Quote
 
 
 
 
Rob Biedenharn
Guest
Posts: n/a
 
      02-04-2009
On Feb 4, 2009, at 1:37 PM, David Stanford wrote:

> Hi all,
>
> I'm having trouble figuring out a way of creating a method within a
> class that's available not only to the other object methods (object
> instances), but also externally, as if I were to use 'self.method'.
> Below is an (admittedly, lame) example of what I'm referring to:
>
> #############################
>
> class CheesePhrase
> def initialize(phrase)
> @phrase = phrase
> say_it
> end
>
> def say_it(phrase=@phrase)
> puts "#{phrase}"
> end
> end
>
> #############################
> <snip/>
> Thanks in advance!
>
> -David


class CheesePhrase
def initialize(phrase)
@phrase = phrase
say_it
end

def self.say_it(phrase)
puts phrase
end
def say_it
self.class.say_it(@phrase)
end
end

irb> some_cheese_phrase = CheesePhrase.new("I like cheese.")
I like cheese.
=> #<CheesePhrase:0x629d0 @phrase="I like cheese.">
irb> some_cheese_phrase.say_it
I like cheese.
=> nil
irb> CheesePhrase.say_it("I like cheese, too.")
I like cheese, too.
=> nil

-Rob

Rob Biedenharn http://agileconsultingllc.com
http://www.velocityreviews.com/forums/(E-Mail Removed)


 
Reply With Quote
 
 
 
 
David Stanford
Guest
Posts: n/a
 
      02-04-2009
Rob Biedenharn wrote:
> On Feb 4, 2009, at 1:37 PM, David Stanford wrote:


> class CheesePhrase
> def initialize(phrase)
> @phrase = phrase
> say_it
> end
>
> def self.say_it(phrase)
> puts phrase
> end
> def say_it
> self.class.say_it(@phrase)
> end
> end


> -Rob
>
> Rob Biedenharn http://agileconsultingllc.com
> (E-Mail Removed)


Thanks a lot, Rob. Is this really the standard way of implementing
something like this? It just seems a little redundant, no?

Thanks!

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

 
Reply With Quote
 
tjnogueira@oomaster.com
Guest
Posts: n/a
 
      02-04-2009
Hi David,
i don't understand well what you need. Is this that you are looking for:
class CheesePhrase
def initialize(phrase)
@phrase = phrase
CheesePhrase.say_it(phrase)
end
def CheesePhrase.say_it(phrase=@phrase)
puts "#{phrase}"
end
end

a = CheesePhrase.new('I like cheese')
a = CheesePhrase.say_it('I like too much cheese);

On Thu, 5 Feb 2009 03:37:30 +0900, David Stanford <(E-Mail Removed)>
wrote:
> Hi all,
>
> I'm having trouble figuring out a way of creating a method within a
> class that's available not only to the other object methods (object
> instances), but also externally, as if I were to use 'self.method'.
> Below is an (admittedly, lame) example of what I'm referring to:
>
> #############################
>
> class CheesePhrase
> def initialize(phrase)
> @phrase = phrase
> say_it
> end
>
> def say_it(phrase=@phrase)
> puts "#{phrase}"
> end
> end
>
> #############################
>
> The above code works fine if I create an object instance, and (if I
> choose to do so) call the method 'say_it', like so:
>
> some_cheese_phrase = CheesePhrase.new("I like cheese.")
> some_cheese_phrase.say_it
>
> However, what if I'd also like to call the method directly, without
> creating a new instance? For example, simply with:
>
> CheesePhrase.say_it("I like cheese, too.")
>
> I can't do this without using 'self.say_it' in the method declaration.
> Though, if I do that, I am no longer able to call the method in
> 'initialize' since 'self.say_it' is now a class method. I get the
> following error:
>
> NoMethodError: undefined method `say_it' for #<CheesePhrase:0x284372f4
> @phrase="I like cheese">
> from (irb):4:in `initialize'
> from (irb):11:in `new'
>
> I'm sure I must be doing something wrong, or my concept of how to
> implement this is totally wrong. The only other thought I've had is to
> create duplicate methods, but this seems to violate the famed DRY
> principle. Any advice would be much appreciated.
>
> Thanks in advance!
>
> -David
> --
> Posted via http://www.ruby-forum.com/.



 
Reply With Quote
 
Rob Biedenharn
Guest
Posts: n/a
 
      02-04-2009
On Feb 4, 2009, at 2:03 PM, David Stanford wrote:
> Rob Biedenharn wrote:
>> On Feb 4, 2009, at 1:37 PM, David Stanford wrote:

>
>> class CheesePhrase
>> def initialize(phrase)
>> @phrase = phrase
>> say_it
>> end
>>
>> def self.say_it(phrase)
>> puts phrase
>> end
>> def say_it
>> self.class.say_it(@phrase)
>> end
>> end

>
>> -Rob
>>
>> Rob Biedenharn http://agileconsultingllc.com
>> (E-Mail Removed)

>
> Thanks a lot, Rob. Is this really the standard way of implementing
> something like this? It just seems a little redundant, no?
>
> Thanks!
>
> -David



When you need it, yes. However, it isn't typical that you'd do
something like this. Either the method belongs on the instance or it
belongs on the class itself. Occasionally, for convenience, you want
a class method to be called on an instance and then you'd likely do it
this way. Your example is simple (and, being an example, somewhat
contrived), but illustrates a point. You can call #say_it with no
parameter because the instance variable is there so an instance
*knows* what to say, but to call .say_it on the class, you need to
pass the parameter.

-Rob

Rob Biedenharn http://agileconsultingllc.com
(E-Mail Removed)



 
Reply With Quote
 
Rick DeNatale
Guest
Posts: n/a
 
      02-04-2009
[Note: parts of this message were removed to make it a legal post.]

On Wed, Feb 4, 2009 at 3:06 PM, Rob Biedenharn
<(E-Mail Removed)>wrote:

>
> When you need it, yes. However, it isn't typical that you'd do something
> like this. Either the method belongs on the instance or it belongs on the
> class itself. Occasionally, for convenience, you want a class method to be
> called on an instance and then you'd likely do it this way. Your example is
> simple (and, being an example, somewhat contrived), but illustrates a point.
> You can call #say_it with no parameter because the instance variable is
> there so an instance *knows* what to say, but to call .say_it on the class,
> you need to pass the parameter.
>


Ruby does have a method Module#module_function which can be used in cases
similar to this. For a rather silly example:

module Test
def foo
puts "Foo"
end

module_function :foo
end

Test.foo

begin
foo
rescue Exception => ex
puts "oops! #{ex}"
end

self.extend Test
foo

when run produces:

Foo
oops! undefined local variable or method `foo' for main:Object
Foo

What module_function does is to copy one or more instance methods and make
them singleton methods of the module. It only works for modules not
classes.

The canonical use case is in the Math module so that you can either write:

Math.sin(.2)

or

class X
include Math

def compute(val)
2 + sin(val)
end
end
--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale

 
Reply With Quote
 
Julian Leviston
Guest
Posts: n/a
 
      02-05-2009
Put "self." in front of the method name in it's definition. This is
called a class method. If you need both, have both.

Blog: http://random8.zenunit.com/
Learn rails: http://sensei.zenunit.com/

On 05/02/2009, at 5:37 AM, David Stanford <(E-Mail Removed)> wrote:

> Hi all,
>
> I'm having trouble figuring out a way of creating a method within a
> class that's available not only to the other object methods (object
> instances), but also externally, as if I were to use 'self.method'.
> Below is an (admittedly, lame) example of what I'm referring to:
>
> #############################
>
> class CheesePhrase
> def initialize(phrase)
> @phrase = phrase
> say_it
> end
>
> def say_it(phrase=@phrase)
> puts "#{phrase}"
> end
> end
>
> #############################
>
> The above code works fine if I create an object instance, and (if I
> choose to do so) call the method 'say_it', like so:
>
> some_cheese_phrase = CheesePhrase.new("I like cheese.")
> some_cheese_phrase.say_it
>
> However, what if I'd also like to call the method directly, without
> creating a new instance? For example, simply with:
>
> CheesePhrase.say_it("I like cheese, too.")
>
> I can't do this without using 'self.say_it' in the method declaration.
> Though, if I do that, I am no longer able to call the method in
> 'initialize' since 'self.say_it' is now a class method. I get the
> following error:
>
> NoMethodError: undefined method `say_it' for #<CheesePhrase:0x284372f4
> @phrase="I like cheese">
> from (irb):4:in `initialize'
> from (irb):11:in `new'
>
> I'm sure I must be doing something wrong, or my concept of how to
> implement this is totally wrong. The only other thought I've had is to
> create duplicate methods, but this seems to violate the famed DRY
> principle. Any advice would be much appreciated.
>
> Thanks in advance!
>
> -David
> --
> Posted via http://www.ruby-forum.com/.
>


 
Reply With Quote
 
David Stanford
Guest
Posts: n/a
 
      02-05-2009
Thanks for all the responses, guys.

Judging from everyone's response, it sounds like what I'm trying to do
isn't typically done. My mindset was, first, to simply create a standard
class. While creating one of the object methods for that class, I
realized that the same method code would be useful to call directly,
without having to create an object instance; so, as I said, I was
thinking there must be some way to do this, without repeating the same
(or a similar piece) of code somewhere else.

So, thanks again!
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Mike Gold
Guest
Posts: n/a
 
      02-06-2009
Rick Denatale wrote:
> Ruby does have a method Module#module_function which can be used in
> cases similar to this. For a rather silly example:
>
> module Test
> def foo
> puts "Foo"
> end
>
> module_function :foo
> end


To make a minor point, I see this use of module_function often, even in
the standard library. I don't like it.

In addition to the module_function method, there's the module_function
scoping state, like public or private or protected, which is likewise
enabled by calling module_function without arguments. Therefore we can
make a D.R.Y. equivalent:

module Test
module_function

def foo
puts "Foo"
end
end
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      02-06-2009
2009/2/5 David Stanford <(E-Mail Removed)>:

> Judging from everyone's response, it sounds like what I'm trying to do
> isn't typically done.


Agreed.

> My mindset was, first, to simply create a standard
> class. While creating one of the object methods for that class, I
> realized that the same method code would be useful to call directly,
> without having to create an object instance; so, as I said, I was
> thinking there must be some way to do this, without repeating the same
> (or a similar piece) of code somewhere else.


In that case I would have the method definition *only* at class level
since apparently it is independent of instance state. I wouldn't even
have it as instance method at all. That avoids confusion. If you
need to invoke the method from instance methods the
self.class.a_method() idiom works well IMHO.

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is there a way to find the class methods of a class, just like'methods' finds the instance methods? Kenneth McDonald Ruby 5 09-26-2008 03:09 PM
object persistency, store instances relationship externally King Python 2 07-25-2008 05:05 PM
jboss will not work externally Dean Harper Java 0 06-12-2006 07:44 PM
Externally Linking Paul Kirby C++ 7 06-28-2004 11:20 PM
open page externally when click on hyperlink inside datagrid Marshal Antony ASP .Net 2 02-27-2004 08:47 AM



Advertisments