Self

class MyClass
  def self.do_something
    puts 'success'
  end
  do_something
end

This puts 'success' - this is a a class method right?

How do I move the "def self..end" section into a module? Trying the obvious:

module MyModule
  def self.do_something
    puts 'success'
  end
end

class MyClass
  include MyModule
  do_something
end

doesn't seem to work, but this does:

module MyModule
  def do_something
    puts 'success'
  end
end

class MyClass
  include MyModule
  def ex
    do_something
  end
end

MyClass.new.ex

Here, is "run" an instance method, which is why it can only be called
from a #new instance? How do I get it to get called from this:

class MyClass
  include MyModule
  do_something
end

Thanks,
Douglas

module MyModule
   def do_something
     puts "success"
   end
end

class MyClass
   extend MyModule
end

MyClass.do_something # ==> success

This will work too:

class MyClass
   extend MyModule
   do_something
end

···

On Apr 13, 2005, at 8:07 PM, Douglas Livingstone wrote:

class MyClass
  def self.do_something
    puts 'success'
  end
  do_something
end

This puts 'success' - this is a a class method right?

How do I move the "def self..end" section into a module? Trying the obvious:

module MyModule
  def self.do_something
    puts 'success'
  end
end

class MyClass
  include MyModule
  do_something
end

doesn't seem to work, but this does:

module MyModule
  def do_something
    puts 'success'
  end
end

class MyClass
  include MyModule
  def ex
    do_something
  end
end

MyClass.new.ex

Here, is "run" an instance method, which is why it can only be called
from a #new instance? How do I get it to get called from this:

class MyClass
  include MyModule
  do_something
end

Thanks,
Douglas

1) use a superclass rather than a module:

  class MySuperClass
    def self.do_something
      puts "success"
    end
  end

  class MyClass < MySuperClass
    do_something
  end

2) use extend instead of include:

  module MyModule
    def do_something
      puts "success"
    end
  end

  class MyClass
    extend MyModule
    do_something
  end

3) get tricky with it and use append_features:

  module MyModule
    def self.append_features( aClass )
      def aClass.do_something
        puts "success"
      end
      super # must do this!
    end
  end

  class MyClass
    include MyModule
    do_something
  end

I do not recommend the later though.

T.

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag news:1113449849.596475.60490@z14g2000cwz.googlegroups.com...

1) use a superclass rather than a module:

class MySuperClass
   def self.do_something
     puts "success"
   end
end

class MyClass < MySuperClass
   do_something
end

Did you verify that this works? :slight_smile:

2) use extend instead of include:

module MyModule
   def do_something
     puts "success"
   end
end

class MyClass
   extend MyModule
   do_something
end

3) get tricky with it and use append_features:

module MyModule
   def self.append_features( aClass )
     def aClass.do_something
       puts "success"
     end
     super # must do this!
   end
end

class MyClass
   include MyModule
   do_something
end

I do not recommend the later though.

Here's what I do if I want to have a set of singleton methods available for all classes in a class hierarchy:

class Base
  module MySpecialClassMethods
    # make inheritance work:
    def inherited(cl) cl.extend MySpecialClassMethods end

    attr_accessor :bar
    def foo() "foo" end
    # other methods...
  end

  extend MySpecialClassMethods
end

class Derived < Base
end

Base.foo

=> "foo"

Derived.foo

=> "foo"

Base.bar = 1

=> 1

Base.bar

=> 1

Derived.bar

=> nil

Derived.bar = 10

=> 10

Derived.bar

=> 10

Base.bar

=> 1

The nice thing is that there is just one copy of those method definitions plus you can change them or add new ones later and automatically all classes in the hiearchy have them.

Some background: you need to use the trick with #inherited() because singleton methods do not inherit along the class hierarchy because the class of all classes is Class.

Base.class

=> Class

Derived.class

=> Class

Kind regards

    robert

Robert Klemme wrote:

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1113449849.596475.60490@z14g2000cwz.googlegroups.com...
> 1) use a superclass rather than a module:
>
> class MySuperClass
> def self.do_something
> puts "success"
> end
> end
>
> class MyClass < MySuperClass
> do_something
> end

Did you verify that this works? :slight_smile:

> 2) use extend instead of include:
>
> module MyModule
> def do_something
> puts "success"
> end
> end
>
> class MyClass
> extend MyModule
> do_something
> end
>
> 3) get tricky with it and use append_features:
>
> module MyModule
> def self.append_features( aClass )
> def aClass.do_something
> puts "success"
> end
> super # must do this!
> end
> end
>
> class MyClass
> include MyModule
> do_something
> end
>
> I do not recommend the later though.

Here's what I do if I want to have a set of singleton methods

available for

all classes in a class hierarchy:

class Base
  module MySpecialClassMethods
    # make inheritance work:
    def inherited(cl) cl.extend MySpecialClassMethods end

    attr_accessor :bar
    def foo() "foo" end
    # other methods...
  end

  extend MySpecialClassMethods
end

class Derived < Base
end

>> Base.foo
=> "foo"
>> Derived.foo
=> "foo"

>> Base.bar = 1
=> 1
>> Base.bar
=> 1
>> Derived.bar
=> nil
>> Derived.bar = 10
=> 10
>> Derived.bar
=> 10
>> Base.bar
=> 1

The nice thing is that there is just one copy of those method

definitions

plus you can change them or add new ones later and automatically all

classes

in the hiearchy have them.

Some background: you need to use the trick with #inherited() because
singleton methods do not inherit along the class hierarchy because

the class

···

of all classes is Class.

>> Base.class
=> Class
>> Derived.class
=> Class

Kind regards

    robert

Robert Klemme wrote:

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1113449849.596475.60490@z14g2000cwz.googlegroups.com...
> 1) use a superclass rather than a module:
>
> class MySuperClass
> def self.do_something
> puts "success"
> end
> end
>
> class MyClass < MySuperClass
> do_something
> end

Did you verify that this works? :slight_smile:

Of course not! :slight_smile: But if that doesn't work then I need go back to
training wheels!!! Did you verify that is doesn't? if so then then
again! ;o)

Here's what I do if I want to have a set of singleton methods

available for

all classes in a class hierarchy:

class Base
  module MySpecialClassMethods
    # make inheritance work:
    def inherited(cl) cl.extend MySpecialClassMethods end

    attr_accessor :bar
    def foo() "foo" end
    # other methods...
  end

  extend MySpecialClassMethods
end

You're right, this is a great approach.

T.

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag news:1113654704.368730.203380@l41g2000cwc.googlegroups.com...

Robert Klemme wrote:

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1113449849.596475.60490@z14g2000cwz.googlegroups.com...
> 1) use a superclass rather than a module:
>
> class MySuperClass
> def self.do_something
> puts "success"
> end
> end
>
> class MyClass < MySuperClass
> do_something
> end

Did you verify that this works? :slight_smile:

Of course not! :slight_smile: But if that doesn't work then I need go back to
training wheels!!! Did you verify that is doesn't? if so then then
again! ;o)

Of course not - cause I *knew* that it does not work. But if that comforts you

class MySuperClass
  def self.do_something
    puts "success"
  end
end

=> nil

?> class MyClass < MySuperClass

  do_something
end

success
=> nil

Oooops... :-)))

Looks like it's rather me that has to go back to school. Now *you* explain why it works.

Here's what I do if I want to have a set of singleton methods

available for

all classes in a class hierarchy:

class Base
  module MySpecialClassMethods
    # make inheritance work:
    def inherited(cl) cl.extend MySpecialClassMethods end

    attr_accessor :bar
    def foo() "foo" end
    # other methods...
  end

  extend MySpecialClassMethods
end

You're right, this is a great approach.

But apparently superfluous

class My2 < MyClass
  do_something
end

success
=> nil

Could it be that this didn't work in older versions? I'm almost sure that I did try this once and it failed. This is strange...

Thanks for crushing my certainty!

Kind regards

    robert

Robert Klemme wrote:

Oooops... :-)))

Looks like it's rather me that has to go back to school. Now *you*

explain

why it works.

Oh dear. Why? Uh.....It just do!

>> Here's what I do if I want to have a set of singleton methods
> available for
>> all classes in a class hierarchy:
>>
>> class Base
>> module MySpecialClassMethods
>> # make inheritance work:
>> def inherited(cl) cl.extend MySpecialClassMethods end
>>
>> attr_accessor :bar
>> def foo() "foo" end
>> # other methods...
>> end
>>
>> extend MySpecialClassMethods
>> end
>
> You're right, this is a great approach.

But apparently superfluous

>> class My2 < MyClass
>> do_something
>> end
success
=> nil

Could it be that this didn't work in older versions? I'm almost sure

that I

did try this once and it failed. This is strange...

Actually I think it always has. But what doesn't is this:

  module MyNotSoSuperModule
    def self.do_something
      puts "success"
    end
  end

class MyClass
   include MyNotSoSuperModule
   do_something
end

#=> undefined local variable or method `do_something' for MyClass:Class
(NameError)

Maybe you got the cases crossed? Actually I got them crossed myself, as
I was thinking your example did us this service by allowing modules to
include class-level methods, but that would actually require using
#included rather then #inherited, like this:

  module Base
    module MySpecialClassMethods
      # make inheritance work:
      def included(cl)
        cl.extend MySpecialClassMethods
        p self, cl
      end

      attr_accessor :bar
      def foo() "foo" end
      # other methods...
    end

    extend MySpecialClassMethods
  end

  class Derived
    include Base
  end

  p Derived.foo

  class Derived2 < Derived
  end

  p Derived2.foo

And that is a good idea, I think.

Thanks for crushing my certainty!

Hey, no problem. I'm an expert at crushing my own, so the least I could
do was share :slight_smile:

T.

robert,

i have one for you. tell me how to create a class whose subclasses DO
NOT inherit some particular state from. In other words I need:

  class Base
     def self.state ; true ; end # or what have you
  end

  class Derived < Base
  end

  Derived.state #=> nil (was NOT inherited)

how do i get something like that to work?

t.

Is this what you're after?

module MySuperDuperModule
  def do_something
    puts "success"
  end
end

class MyClass
  extend MySuperDuperModule
  do_something
end

#=> success

Sean

···

On Sun, 2005-04-17 at 01:14 +0900, Trans wrote:

Actually I think it always has. But what doesn't is this:

  module MyNotSoSuperModule
    def self.do_something
      puts "success"
    end
  end

class MyClass
   include MyNotSoSuperModule
   do_something
end

[quote Trans::on 4/16/2005 7:34 PM]

robert,

i have one for you. tell me how to create a class whose subclasses DO
NOT inherit some particular state from. In other words I need:

  class Base
     def self.state ; true ; end # or what have you
  end

  class Derived < Base
  end

  Derived.state #=> nil (was NOT inherited)

how do i get something like that to work?

t.

absolutely ruby newbie 2c:

probably private will do this.

- --
:alex |.::the_mindstorm::.|

Hi Sean,

Is this what you're after?

:slight_smile: Yes that works. BUT, I shy away from it becuase it forces me to
maintian two separate enclosures: one for extend and another for
include. If all I need is the extend functionality then its okay, but
usually that is not the case.

T.

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag news:1113672669.627263.226310@f14g2000cwb.googlegroups.com...

robert,

i have one for you. tell me how to create a class whose subclasses DO
NOT inherit some particular state from. In other words I need:

class Base
    def self.state ; true ; end # or what have you
end

class Derived < Base
end

Derived.state #=> nil (was NOT inherited)

how do i get something like that to work?

Hey, that's an easy one:

class Base
  class << self
    attr :state
  end
  instance_variable_set "@state", true
end

class Derived < Base
end

?> Base.state
=> true

Derived.state

=> nil

:slight_smile:

State is never inherited. The reason why your code didn't do what you wanted was that the implementation of the method was inherited.

Btw, I would find something like this useful in the std lib:

class Class
  def properties(*h)
    h = h[0] if h.size == 1
    initial = {}

    h.each do |name, val|
      attr_accessor name
      initial[name]=val unless val.nil?
    end

    unless initial.empty?
      alias :new_plain :new
      class<<self;self;end.instance_eval do
        define_method(:new) do |*a|
          obj = allocate
          initial.each {|name, val| obj.send("#{name}=".to_sym, val)}
          obj.instance_eval { initialize(*a) }
          obj
        end
      end
    end

    h
  end
end

class Foo
  properties( :name => "foo", :age => 10 )
end

=> {:age=>10, :name=>"foo"}

Foo.new.name

=> "foo"

class Bar
  properties :name, :age
end

=> [:name, :age]

Bar.new.name

=> nil

Cheers

    robert

Hi Trans,

···

On Sun, 2005-04-17 at 08:19 +0900, Trans wrote:

If all I need is the extend functionality then its okay, but
usually that is not the case.

What is usually the case? (I'm curious because I'm experimenting with
DSLs at the moment and wonder why you would want to mix together class
instance inheritance with object instance inheritance).

Regards,

Sean

Robert Klemme wrote:

Hey, that's an easy one:

class Base
  class << self
    attr :state
  end
  instance_variable_set "@state", true
end

class Derived < Base
end

?> Base.state
=> true
>> Derived.state
=> nil

:slight_smile:

State is never inherited. The reason why your code didn't do what

you

wanted was that the implementation of the method was inherited.

Ah, of course! --Until this thread I never really gave much thought to
setting instance varaible in the class scope like this. Your simple
example makes it quite plain. That'll be helpful, now that I see it
clearly. Thank you.

Btw, I would find something like this useful in the std lib:

class Class
  def properties(*h)
    h = h[0] if h.size == 1
    initial = {}

    h.each do |name, val|
      attr_accessor name
      initial[name]=val unless val.nil?
    end

    unless initial.empty?
      alias :new_plain :new
      class<<self;self;end.instance_eval do
        define_method(:new) do |*a|
          obj = allocate
          initial.each {|name, val| obj.send("#{name}=".to_sym, val)}
          obj.instance_eval { initialize(*a) }
          obj
        end
      end
    end

    h
  end
end

>> class Foo
>> properties( :name => "foo", :age => 10 )
>> end
=> {:age=>10, :name=>"foo"}
>> Foo.new.name
=> "foo"
>> class Bar
>> properties :name, :age
>> end
=> [:name, :age]
>> Bar.new.name
=> nil

:slight_smile: Ara sent me something much like this recently, too. And something
like them is in route to Ruby Carats for sure. Thanks for helpful code.

T.

Robert Klemme wrote:

Btw, I would find something like this useful in the std lib:

class Class
  def properties(*h)
    h = h[0] if h.size == 1
    initial = {}

    h.each do |name, val|
      attr_accessor name
      initial[name]=val unless val.nil?
    end

    unless initial.empty?
      alias :new_plain :new
      class<<self;self;end.instance_eval do
        define_method(:new) do |*a|
          obj = allocate
          initial.each {|name, val| obj.send("#{name}=".to_sym, val)}
          obj.instance_eval { initialize(*a) }
          obj
        end
      end
    end

    h
  end
end

Ubfortunately, I think it is a bit dangerous to mess with #new like
this as a standard practice. Yet I do not see any other way to set the
instance vars. Agree or no?

T.

"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1113782539.239967.177710@z14g2000cwz.googlegroups.com...

Robert Klemme wrote:
> Btw, I would find something like this useful in the std lib:
>
> class Class
> def properties(*h)
> h = h[0] if h.size == 1
> initial = {}
>
> h.each do |name, val|
> attr_accessor name
> initial[name]=val unless val.nil?
> end
>
> unless initial.empty?
> alias :new_plain :new
> class<<self;self;end.instance_eval do
> define_method(:new) do |*a|
> obj = allocate
> initial.each {|name, val| obj.send("#{name}=".to_sym, val)}
> obj.instance_eval { initialize(*a) }
> obj
> end
> end
> end
>
> h
> end
> end

Ubfortunately, I think it is a bit dangerous to mess with #new like
this as a standard practice. Yet I do not see any other way to set the
instance vars. Agree or no?

Yes - for current versions. But with wrappers (or hooks) this will be
easier in 2.0 I guess.

Kind regards

    robert