Opinion on ClassInherit Include

So I want to include a module and have methods become part of the class, not
the instance. What do others think of this approach?

  class Module
    alias :append_instance_features :append_features
    def append_features(klass)
      if constants.include?("ClassInherit")
        klass.extend self::ClassInherit
      end
      append_instance_features(klass)
    end
  end

Example:

  module MyMod
    module ClassInherit
      attr_accessor :x
      def hix
        puts "Hi, #{@x}."
      end
    end
    # ...
  end

  class A
    include MyMod
  end

  A.x = 'you'
  A.hix #=> Hi, you.

···

--
T.

So I want to include a module and have methods become part of the class, not
the instance. What do others think of this approach?

svg% cat b.rb
#!/usr/bin/ruby
module MyMod
   attr_accessor :x
   def hix
      puts "Hi, #{@x}."
   end
end

class A
   extend MyMod
end

A.x = 'you'
A.hix #=> Hi, you.
svg%

svg% b.rb
Hi, you.
svg%

Guy Decoux

You missed the '# ...' in the example. So that dosen't work. You end up having
to have two seperate modules, one of which is included the other of which is
extended. I want a single encapsulation. To clarify:

  module MyMod
module ClassInherit
attr_accessor :x
def hix
puts "Hi, #{@x}."
end
end
def hey
      puts "Me, too."
    end
end

class A
include MyMod
end

A.x = 'you'
A.hix #=> Hi, you.
  A.new.hey #=> Me, too.

···

On Saturday 14 August 2004 09:41 am, ts wrote:

svg% cat b.rb
#!/usr/bin/ruby
module MyMod
   attr_accessor :x
   def hix
      puts "Hi, #{@x}."
   end
end

class A
   extend MyMod
end

A.x = 'you'
A.hix #=> Hi, you.
svg%

--
T.

You missed the '# ...' in the example. So that dosen't work. You end up having
to have two seperate modules, one of which is included the other of which is
extended. I want a single encapsulation. To clarify:

[ryby-talk:39574] but probably this example was given previously.

Guy Decoux

"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408140954.24066.transami@runbox.com...

> svg% cat b.rb
> #!/usr/bin/ruby
> module MyMod
> attr_accessor :x
> def hix
> puts "Hi, #{@x}."
> end
> end
>
> class A
> extend MyMod
> end
>
> A.x = 'you'
> A.hix #=> Hi, you.
> svg%

You missed the '# ...' in the example. So that dosen't work. You end up

having

to have two seperate modules, one of which is included the other of which

is

extended. I want a single encapsulation.

You didn't say so in your original post. And as far as I can see you have
two modules in your example, too. As you obviously noticed, you need to
identify those parts that should go into instances and those for the class
*somehow*. So having two separate modules is really the simplest way.

Kind regards

    robert

···

On Saturday 14 August 2004 09:41 am, ts wrote:

Hi --

> svg% cat b.rb
> #!/usr/bin/ruby
> module MyMod
> attr_accessor :x
> def hix
> puts "Hi, #{@x}."
> end
> end
>
> class A
> extend MyMod
> end
>
> A.x = 'you'
> A.hix #=> Hi, you.
> svg%

You missed the '# ...' in the example. So that dosen't work. You end up having
to have two seperate modules, one of which is included the other of which is
extended. I want a single encapsulation. To clarify:

  module MyMod
module ClassInherit
attr_accessor :x
def hix
puts "Hi, #{@x}."
end
end
def hey
      puts "Me, too."
    end
end

class A
include MyMod
end

A.x = 'you'
A.hix #=> Hi, you.
  A.new.hey #=> Me, too.

As Robert pointed out, you've already got two modules. I think that's
OK, and it's probably better just to do the most direct thing with
them (i.e., use include and extend to modify the behavior of the
objects you want to change, rather than add a special-case layer for
extending class objects).

If you want to have them nested, you could perhaps do:

  module MyMod
    module Inner
      attr_accessor :x
      def hix
        puts "Hi, #{@x}."
      end
    end
    def blah
      puts "hi"
    end
  end

  class A
    include MyMod
    extend Inner
  end

  A.x = 'you'
  A.hix # => Hi, you.
  A.new.blah # => hi

David

···

On Sat, 14 Aug 2004, T. Onoma wrote:

On Saturday 14 August 2004 09:41 am, ts wrote:

--
David A. Black
dblack@wobblini.net

The way I handle these situations is:

module MyMod
    
    class << self
        def included(klass)
            # Also extend the class with
            # the features in ClassMixin
            klass.__send__(:extend, ClassMixin)
        end
    end
    
    module ClassMixin
        attr_accessor :x
        def hix
            puts "Hi, #{@x}."
        end
    end
    
    def hey
        puts "Me, too"
    end
end

class A
    include MyMod
end

HTH. //Anders

···

On Sat, Aug 14, 2004 at 10:54:28PM +0900, T. Onoma wrote:

On Saturday 14 August 2004 09:41 am, ts wrote:
> svg% cat b.rb
> #!/usr/bin/ruby
> module MyMod
> attr_accessor :x
> def hix
> puts "Hi, #{@x}."
> end
> end
>
> class A
> extend MyMod
> end
>
> A.x = 'you'
> A.hix #=> Hi, you.
> svg%

You missed the '# ...' in the example. So that dosen't work. You end up having
to have two seperate modules, one of which is included the other of which is
extended. I want a single encapsulation. To clarify:

  module MyMod
module ClassInherit
attr_accessor :x
def hix
puts "Hi, #{@x}."
end
end
def hey
      puts "Me, too."
    end
end

class A
include MyMod
end

A.x = 'you'
A.hix #=> Hi, you.
  A.new.hey #=> Me, too.

--
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Anders Engström aengstrom@gnejs.net
. http://www.gnejs.net PGP-Key: ED010E7F
. [Your mind is like an umbrella. It doesn't work unless you open it.]

Okay, more detail then.

Currently I have a class that can be subclassed to inherit behavior, but I
want to turn that into a mixin module instead. Problem is that the class has
class methods that need to be inherited too. Can't do that with a module, so
I had to figure out a way. Of course I could use two *seperate* modules, as
you say, but then the lib user would have to add two lines of code (an
include and an extend) to get functionality that really belongs together.

So let me ask it this way: I have class behavior and instance behavior that
needs to encapsulated into a single mixin unit. How to do it?

···

On Saturday 14 August 2004 10:06 am, Robert Klemme wrote:

You didn't say so in your original post. And as far as I can see you have
two modules in your example, too. As you obviously noticed, you need to
identify those parts that should go into instances and those for the class
*somehow*. So having two separate modules is really the simplest way.

--
T.

Using the callback here. That works too. I'm wondering if this kind of
functionality is desireable enough to warrent some kind of RCR.

···

On Saturday 14 August 2004 11:47 am, Anders Engström wrote:

The way I handle these situations is:

module MyMod

    class << self
        def included(klass)
            # Also extend the class with
            # the features in ClassMixin
            klass.__send__(:extend, ClassMixin)
        end
    end

    module ClassMixin
        attr_accessor :x
        def hix
            puts "Hi, #{@x}."
        end
    end

    def hey
        puts "Me, too"
    end
end

--
T.

Hi --

> You didn't say so in your original post. And as far as I can see you have
> two modules in your example, too. As you obviously noticed, you need to
> identify those parts that should go into instances and those for the class
> *somehow*. So having two separate modules is really the simplest way.

Okay, more detail then.

Currently I have a class that can be subclassed to inherit behavior, but I
want to turn that into a mixin module instead. Problem is that the class has
class methods that need to be inherited too. Can't do that with a module, so
I had to figure out a way. Of course I could use two *seperate* modules, as
you say, but then the lib user would have to add two lines of code (an
include and an extend) to get functionality that really belongs together.

So let me ask it this way: I have class behavior and instance behavior that
needs to encapsulated into a single mixin unit. How to do it?

There's no way to redefine Ruby's sense of a mixin, which happens one
transaction at a time. But if you want to do it all in one command,
you could do:

  class Module
    def dual_mixin(mod)
      include mod
      extend mod::Inner
    end
  end

  module MyMod
    module Inner
      def x
  puts "hi"
      end
    end
    def y
      puts "hy"
    end
  end

  class C
    dual_mixin MyMod
  end

  C.x # hi
  C.new.y # hy

While this carries the usual dangers of adding on to base classes, I
think it's better than actually redefining an existing method of
Module. It also draws attention to the fact that two transactions are
taking place, which in turn makes the subsequent code easier to
understand.

David

···

On Sat, 14 Aug 2004, T. Onoma wrote:

On Saturday 14 August 2004 10:06 am, Robert Klemme wrote:

--
David A. Black
dblack@wobblini.net

"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408141028.42017.transami@runbox.com...

> You didn't say so in your original post. And as far as I can see you

have

> two modules in your example, too. As you obviously noticed, you need to
> identify those parts that should go into instances and those for the

class

> *somehow*. So having two separate modules is really the simplest way.

Okay, more detail then.

Currently I have a class that can be subclassed to inherit behavior, but I
want to turn that into a mixin module instead. Problem is that the class

has

class methods that need to be inherited too. Can't do that with a module,

so

I had to figure out a way. Of course I could use two *seperate* modules,

as

you say, but then the lib user would have to add two lines of code (an
include and an extend) to get functionality that really belongs together.

So let me ask it this way: I have class behavior and instance behavior

that

needs to encapsulated into a single mixin unit. How to do it?

You probably want this which works with a single (!) module. Ha!

module Foo
  class <<self
    attr_accessor :foo
  end

  attr_accessor :bar

  def self.append_features(cl)
    # need a copy of me to avoid state interference
    copy = dup
    cls = class<<cl;self;end

    copy.singleton_methods.each do |m|
      cls.send(:define_method, m, copy.method(m).to_proc)
    end

    super
  end
end
Foo.foo = "Foo.foo"
p Foo.foo

class Bar
  include Foo
end

bar = Bar.new
bar.bar = "bar.bar"
p bar.bar

Bar.foo = "Bar.foo"
p Bar.foo
# ensure Foo.foo is unchanged
p Foo.foo

Regards

    robert

···

On Saturday 14 August 2004 10:06 am, Robert Klemme wrote:

"Robert Klemme" <bob.news@gmx.net> schrieb im Newsbeitrag
news:2o6nn5F7gml3U1@uni-berlin.de...

"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408141028.42017.transami@runbox.com...
> > You didn't say so in your original post. And as far as I can see you
have
> > two modules in your example, too. As you obviously noticed, you need

to

> > identify those parts that should go into instances and those for the
class
> > *somehow*. So having two separate modules is really the simplest way.
>
> Okay, more detail then.
>
> Currently I have a class that can be subclassed to inherit behavior, but

I

> want to turn that into a mixin module instead. Problem is that the class
has
> class methods that need to be inherited too. Can't do that with a

module,

so
> I had to figure out a way. Of course I could use two *seperate* modules,
as
> you say, but then the lib user would have to add two lines of code (an
> include and an extend) to get functionality that really belongs

together.

>
> So let me ask it this way: I have class behavior and instance behavior
that
> needs to encapsulated into a single mixin unit. How to do it?

You probably want this which works with a single (!) module. Ha!

This is a bit nicer:

module Foo
  # class code
  class <<self
    attr_accessor :foo

    def append_features(cl)
      # need a copy of me to avoid state interference
      copy = dup
      cls = class<<cl;self;end

      copy.singleton_methods.each do |m|
        cls.send(:define_method, m, copy.method(m).to_proc)
      end

      super
    end
  end

  # instance code
  attr_accessor :bar
end

···

> On Saturday 14 August 2004 10:06 am, Robert Klemme wrote:

Foo.foo = "Foo.foo"
p Foo.foo

class Bar
  include Foo
end

bar = Bar.new
bar.bar = "bar.bar"
p bar.bar

Bar.foo = "Bar.foo"
p Bar.foo
# ensure Foo.foo is unchanged
p Foo.foo

Regards

    robert

That's pretty clever! And I think that's the kind of functionality most people
would expect. It certainly was what I was looking for... at first.

But now I'm shying away from module class-level methods. In fact, I'm putting
almost all methods into modules now and including/extending them where I need
them. Its to the point that I can clearly identify three type of modules:
mixin, service and namespace. And the service modules I've started writting
just like the mixins but with extend self:

  module AService
    extend self
    def ameth
      ...
    end
    ...
  end

···

On Saturday 14 August 2004 11:06 am, Robert Klemme wrote:

This is a bit nicer:

module Foo
  # class code
  class <<self
    attr_accessor :foo
    def append_features(cl)
      # need a copy of me to avoid state interference
      copy = dup
      cls = class<<cl;self;end
      copy.singleton_methods.each do |m|
        cls.send(:define_method, m, copy.method(m).to_proc)
      end
      super
    end
  end
  # instance code
  attr_accessor :bar
end

--
T.

"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408151822.07121.transami@runbox.com...

It certainly was what I was looking for... at first.

But now I'm shying away from module class-level methods. In fact, I'm

putting

almost all methods into modules now and including/extending them where I

need

them. Its to the point that I can clearly identify three type of modules:
mixin, service and namespace. And the service modules I've started

writting

just like the mixins but with extend self:

What made you change your mind? I mean, this is exactly what I suggested in
the first place.

Regards

    robert

Sorry, I probably wasn't clear enough. It wasn't so much that I changed my
mind, as I just decided that I prefer the methods at the instance level. The
difference between this:
  
  module Foo
    class << eval
      def foo
        ...
      end
    end
  end

And this

  module Foo
    def foo
      ...
    end
  end

At first I was trying to get the former's class-level method to be "class
inheritable" on include (which is what your example succeeds at quite
nicely). But now I'm thinking I like using the later better b/c the code is
more reusable in that form.

That's all I meant. I'm still doing the same thing --using a module in a
module. Although I'm not modifying the Module class itself to do the work
anymore.

Hmmm...That makes me wonder. Who has found a NECESSARY use for modules that
have BOTH mixable methods AND class-level methods?

···

On Monday 16 August 2004 05:11 am, Robert Klemme wrote:

What made you change your mind? I mean, this is exactly what I suggested
in the first place.

--
T.

"T. Onoma" <transami@runbox.com> schrieb im Newsbeitrag
news:200408160908.33287.transami@runbox.com...

> What made you change your mind? I mean, this is exactly what I

suggested

> in the first place.

Sorry, I probably wasn't clear enough. It wasn't so much that I changed my
mind, as I just decided that I prefer the methods at the instance level.

The

difference between this:

  module Foo
    class << eval
      def foo
        ...
      end
    end
  end

And this

  module Foo
    def foo
      ...
    end
  end

At first I was trying to get the former's class-level method to be "class
inheritable" on include (which is what your example succeeds at quite
nicely). But now I'm thinking I like using the later better b/c the code

is

more reusable in that form.

That's all I meant. I'm still doing the same thing --using a module in a
module. Although I'm not modifying the Module class itself to do the work
anymore.

So, if I do understand correctly, basically you decided that all "functions"
(i.e. methods you implemented in the module singleton) could go into
instances as well. You probably put them into the module singleton class
because they encapsulated some algorithm that needed no instance state
(hence "functions").

Hmmm...That makes me wonder. Who has found a NECESSARY use for modules

that

have BOTH mixable methods AND class-level methods?

All scenarios where that require a per class bookkeeping of what instances
do, which you apparently didn't need.

    robert

···

On Monday 16 August 2004 05:11 am, Robert Klemme wrote:

So, if I do understand correctly, basically you decided that all "functions"
(i.e. methods you implemented in the module singleton) could go into
instances as well. You probably put them into the module singleton class
because they encapsulated some algorithm that needed no instance state
(hence "functions").

That's right. By having the methods at the instance level, I can then include or extend as the case warrents (or needs change).

> Hmmm...That makes me wonder. Who has found a NECESSARY use for modules
that have BOTH mixable methods AND class-level methods?

All scenarios where that require a per class bookkeeping of what instances
do, which you apparently didn't need.

Yes, that's true. And I can see that for Classes. But for Modules, their class-level methods aren't inhertable (at least not normally --one can of course use your singleton method copier). So I'm still not sure the two are every really required in the same context. One might do it just for some orginizational reason, I suppose. I.e. These "functions" (per your definition) are useful to these mixable instance methods.

T.