[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Re: mixing in class methods

Nathaniel Talbott

10/2/2003 1:27:00 AM

Mark J. Reed [mailto:markjreed@mail.com] wrote:

> Okay, those both work, assuming all I want is class methods
> from the module. I'm guessing I have to break it up. The
> original idea was to have a single module, which defined both
> class and instance methods, which I could
> include/extend/whatever into a class, and then that class
> would have both the instance methods (as instance methods)
> and the class methods (as class methods) from the module.

I've used something like this before:

module M
def self.append_features(klass)
class << klass
def class_method
p "class_method"
end
end
super
end

def instance_method
p "instance_method"
end
end

class C
include M
end

C.class_method
C.new.instance_method


Gotta love that Ruby!


Nathaniel

<:((><


6 Answers

Mark J. Reed

10/2/2003 2:08:00 AM

0

On Thu, Oct 02, 2003 at 10:26:48AM +0900, Nathaniel Talbott wrote:
> I've used something like this before:
>
> module M
> def self.append_features(klass)
> class << klass
> def class_method
> p "class_method"
> end
> end
> super
> end

Perfect! I keep forgetting that most of the innards of Ruby are
themselves Ruby. Darn handy, that. :)

Thanks!

-Mark

Christoph

10/2/2003 4:47:00 AM

0

"Nathaniel Talbott" wrote:
....
> module M
> def self.append_features(klass)
> class << klass
> def class_method
> p "class_method"
> end
> end
> super
> end

Actually the append_feature + super trick is somewhat
outdated in 1.8.0 - use #included instead.

---
module M
end

class << M
module ClassMethods # this avoids name pollution
def class_method1
p "class_method"
end
def class_method2
p "class_method2"
end
end
def included(mod)
if mod.is_a? Class
mod.extend ClassMethods
else
# maybe raise an exception ?
raise "bla ..."
end
end
end

class C
include M
end
---


/Christoph


Robert Klemme

10/2/2003 8:52:00 AM

0


"Christoph" <swap(news_chr)@gmx.net> schrieb im Newsbeitrag
news:blgajs$30q6$1@ulysses.news.tiscali.de...
> "Nathaniel Talbott" wrote:
> ...
> > module M
> > def self.append_features(klass)
> > class << klass
> > def class_method
> > p "class_method"
> > end
> > end
> > super
> > end
>
> Actually the append_feature + super trick is somewhat
> outdated in 1.8.0 - use #included instead.
>
> ---
> module M
> end
>
> class << M
> module ClassMethods # this avoids name pollution
> def class_method1
> p "class_method"
> end
> def class_method2
> p "class_method2"
> end
> end
> def included(mod)
> if mod.is_a? Class
> mod.extend ClassMethods
> else
> # maybe raise an exception ?
> raise "bla ..."
> end
> end
> end
>
> class C
> include M
> end
> ---

This looks a bit complicated to me. IMHO you achieve the same with this
much shorter version_

module M
def class_method1
p "class_method"
end
def class_method2
p "class_method2"
end
end

class C
extend M
end


alternatively:

class C
class << self
include M
end
end

Regards

robert

Mark J. Reed

10/2/2003 1:44:00 PM

0

On Thu, Oct 02, 2003 at 10:51:52AM +0200, Robert Klemme wrote:
> This looks a bit complicated to me. IMHO you achieve the same with this
> much shorter version_
>
> module M
> def class_method1
> p "class_method"
> end
> def class_method2
> p "class_method2"
> end
> end

Yes, but what if you add a 'def instance_method1' to M? Class C
doesn't get it via either approach you cite; it shows up as a class method
instead. All of this circumlocution has been to allow a module to
define BOTH class AND instance methods.

Thanks to all. The :append_features solution was giving me trouble
with modules that included other modules; :included may help there.

-Mark

Christoph

10/3/2003 5:35:00 AM

0


"Robert Klemme" wrote:
....
> module M
> def class_method1
> p "class_method"
> end
> def class_method2
> p "class_method2"
> end
> end
>
> class C
> extend M
> end

Hm, just being my silly self, what about the following
solution for the combined include + extend problem?


---
class WiredModule < Module
private
def extend_object(obj)
super
extended(obj)
end
def extended(obj)
end
end


ClassMethods = WiredModule.new do
def class_method1
p "class_method1"
end
def class_method2
p "class_method2"
end
end


class << ClassMethods
module M
def instance_method1
p "instance_method1"
end
end
def extended(mod)
mod.instance_eval { include M }
end
end

class C
extend ClassMethods
end

C.new.instance_method1 # "instance_method1"
C.class_method1 # "class_method1"
---


/Christoph


Christoph

10/3/2003 6:37:00 AM

0

"Mark J. Reed" wrote:
....
>
> Thanks to all. The :append_features solution was giving me trouble
> with modules that included other modules; :included may help there.

On a serious note: The following might give you an idea on
dealing with the ``include Modules in other Module'' issue.

----
class MModule < Module # the name is arbitrary
def initialize
@class_module = Module.new
super
end
private
def class_methods(&b)
@class_module.module_eval &b
end
def included(mod)
if mod.is_a? Class
mod.extend @class_module
else mod.is_a? MModule
mod.class_module.__send__(:include,@class_module)
end
end
protected
attr_reader :class_module
end




# usage #
M = MModule.new do
def instance_method1
p "instance_method1"
end
class_methods do
def class_method1
p "class_method1"
end
end
end

# a MModule constant can be used like regular Module constant
module M
def instance_method2
p "instance_method2"
end
class_methods do
def class_method2
p "class_method2"
end
end
end


# include example
N = MModule.new do
include M
def instance_method3
p "instance_method1"
end

class_methods do
def class_method3
p "class_method3"
end
end
end


class C
include N
end


C.new.instance_method1 # instance_method1
C.new.instance_method2 # instance_method2
C.new.instance_method3 # instance_method3
C.class_method1 # class_method1
C.class_method2 # class_method2
C.class_method3 # class_method3
----

/Christoph