self

  • Thread starter Douglas Livingstone
  • Start date
D

Douglas Livingstone

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
 
G

Gennady Bystritsky

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
 
T

Trans

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.
 
R

Robert Klemme

Trans said:
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? :)
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
=> "foo"
=> 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.
=> Class

Kind regards

robert
 
T

Trans

Robert said:
Did you verify that this 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

class Derived < Base
end

=> "foo"

=> 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.

=> Class

Kind regards

robert
 
T

Trans

Robert said:
Did you verify that this works? :)

Of course not! :) 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.
 
R

Robert Klemme

Trans said:
Of course not! :) 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
success
=> nil
Oooops... :)))

Looks like it's rather me that has to go back to school. Now *you* explain
why it works.
You're right, this is a great approach.

But apparently superfluous
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
 
T

Trans

Robert said:
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!
But apparently superfluous

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 :)

T.
 
T

Trans

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.
 
A

Alexandru Popescu

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

[quote Trans::eek:n 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::.|
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (MingW32)

iD8DBQFCYV1WOCPjdDT2FEURAq1iAJ46ld2XYqKDXd1jVuJuvp+wEpnb+QCgsbf7
bTreChtwhdxKBXVlMGUpsK4=
=cyQ2
-----END PGP SIGNATURE-----
 
S

Sean O'Halpin

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

Is this what you're after?

module MySuperDuperModule
def do_something
puts "success"
end
end

class MyClass
extend MySuperDuperModule
do_something
end

#=> success

Sean
 
T

Trans

Hi Sean,
Is this what you're after?

:) 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.
 
S

Sean O'Halpin

Hi Trans,

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
 
R

Robert Klemme

Trans said:
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=> nil

:)

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
 
T

Trans

Robert said:
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
=> nil

:)

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

:) 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.
 
T

Trans

Robert said:
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.
 
R

Robert Klemme

Trans said:
Robert said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top