include and extend Module - Ruby Way

A

Alexandru Popescu

Hi!

I am reading the excellent The Ruby Way. I most probably not understand correctly the following pieces:

[quote page=38]
With include, the module's methods become available as instance methods; with extend, they become
available as class methods
[/quote]

I have written the following code example:

Code:
module ExampleModule
def moduleMethod
puts 'module method'
end
end

class IncludeModule
include ExampleModule
end

class ExtendModule
extend ExampleModule
end

im = IncludeModule.new
# IncludeModule.moduleMethod # this is correct
im.moduleMethod # module method becomes instance method

em = ExtendModule.new
ExtendModule.moduleMethod # module method becomes class method
em.moduleMethod # this is failing! WHY?

As pointed above the em#moduleMethod is failing. Being a class method I expect it to be available
also on every instance. What I wrongly understood?

Later I can read the following:

[quote page=275]
The extend method will mix a module into an object. The instance methods from the module become
instance methods for the object.
[/quote]

Isn't this in contradiction with the first quote?

Please enlighten me.

:alex |.::the_mindstorm::.|
 
C

Charles Steinman

Alexandru said:
As pointed above the em#moduleMethod is failing. Being a class method I expect it to be available
also on every instance. What I wrongly understood?

Class methods are members of the class, not of instances of the class.
For instance, Object.new calls the class method new of Object, but you
can't do Object.new.new, because new is not an instance method.
Later I can read the following:

[quote page=275]
The extend method will mix a module into an object. The instance methods from the module become
instance methods for the object.

Isn't this in contradiction with the first quote?[/QUOTE]

The first quote had to do with classes; this one is talking about
instances. Telling an object "extend SomeModule" tells it to add the
methods in SomeModule to itself. In the case of a class, these will
become methods of that class. In the case of a class instance, they
will become methods of that instance.

Does that make more sense?
 
A

Alexandru Popescu

#: Charles Steinman changed the world a bit at a time by saying on 8/21/2005 9:51 AM :#
Class methods are members of the class, not of instances of the class.
For instance, Object.new calls the class method new of Object, but you
can't do Object.new.new, because new is not an instance method.

Thanks Charles. I start to see the end tunnel light. It is the same as:

Code:
class ClassExample
def ClassExample.do_something
p "class method too"
end
end

ClassExample.do_something # class method too
cls= ClassExample.new
cls.do_something # => NoMethodError

Coming from the Java world, for me a class method is a (static) method available withouth a self
(this) reference, but it is available/callable from any instance. (is this available in Ruby?)

It seems that in Ruby the class method is a method belonging to the class ClassExample object.

How can I avoid this term confusion? (at least in my head).

:alex |.::the_mindstorm::.|
Later I can read the following:

[quote page=275]
The extend method will mix a module into an object. The instance methods from the module become
instance methods for the object.

Isn't this in contradiction with the first quote?

The first quote had to do with classes; this one is talking about
instances. Telling an object "extend SomeModule" tells it to add the
methods in SomeModule to itself. In the case of a class, these will
become methods of that class. In the case of a class instance, they
will become methods of that instance.

Does that make more sense?
[/QUOTE]
 
G

Gavin Kistner

Coming from the Java world, for me a class method is a (static)
method available withouth a self (this) reference, but it is
available/callable from any instance. (is this available in Ruby?)

Sorry, I don't know Java (any more). Are you describing a global
function that is only available to instance methods of a certain
class, which is invoked without an explicit receiver?

Something like:
class Foo
def foo_m
x = my_utility_function( )
end
end

class Bar
def bar_m
x = my_utility_function( )
end
end

f = Foo.new
f.foo_m #works

b = Bar.new
b.bar_m #raises an error because my_utility_function() isn't
available to Bar instances

It seems that in Ruby the class method is a method belonging to the
class ClassExample object.

Yup, that's the case. Classes are objects too. So you can do:

class Foo
def self.upcount #same as def Foo.upcount
@instances ||= 0
@instances += 1
end

def self.getcount
@instances
end


def initialize
self.class.upcount
end

def count_neighbors
self.class.getcount
end
end

f1 = Foo.new
f2 = Foo.new
f3 = Foo.new
p f1.count_neighbors #=> 3


As you can see above, the Class has its own scope for its own
instance variable. The class itself is a completely separate instance
of the "Class" class, which just happens to be tied to instances of
it in a few special ways.
 
A

Alexandru Popescu

#: Gavin Kistner changed the world a bit at a time by saying on 8/21/2005 4:36 PM :#
Sorry, I don't know Java (any more). Are you describing a global
function that is only available to instance methods of a certain
class, which is invoked without an explicit receiver?

Nope. I was talking about:
Code:
public class ExampleClass {
public static void staticMethod() {
// illegal access to any instance field
System.out.println("staticMethod");
}
}

ExampleClass.staticMethod(); // prints the message; no instance of ExampleClass is available
ExampleClass ec= new ExampleClass();
ec.staticMethod(); // prints the message; not recommended but works
[QUOTE]
Yup, that's the case. Classes are objects too. So you can do:

class Foo
def self.upcount   #same as def Foo.upcount
@instances ||= 0
@instances += 1
end

def self.getcount
@instances
end


def initialize
self.class.upcount
end

def count_neighbors
self.class.getcount
end
end

f1 = Foo.new
f2 = Foo.new
f3 = Foo.new
p f1.count_neighbors #=> 3


As you can see above, the Class has its own scope for its own
instance variable. The class itself is a completely separate instance
of the "Class" class, which just happens to be tied to instances of
it in a few special ways.
[/QUOTE]

Writting some more examples I think I got the idea. It is subtle difference that I don't know how to
describe in words :-s. (the class method in Ruby belongs only to the new defined class, but not to
its instances, while in Java the class method belongs to the new defined class and all its instances).

:alex |.::the_mindstorm::.|
 
G

Gavin Kistner

Sorry, I don't know Java (any more). Are you describing a global
function that is only available to instance methods of a certain
class, which is invoked without an explicit receiver?

Nope. I was talking about:
Code:
public class ExampleClass {
public static void staticMethod() {
// illegal access to any instance field
System.out.println("staticMethod");
}
}

ExampleClass.staticMethod(); // prints the message; no instance of
ExampleClass is available
ExampleClass ec= new ExampleClass();
ec.staticMethod(); // prints the message; not recommended but works[/QUOTE]

I don't know of a built-in mechanism to do this in Ruby, other than
something like:

class Foo
def self.staticMethod
puts "staticMethod"
end
def staticMethod
self.class.staticMethod
end
end

There are things you could do to make it easier to set this up, so
you might only have to type something like:
class Foo
static_method :foo {
# your_code_here
}
end
but that would just be a fancy interface to setting up a method on
both the class and its instances.


You say that it's not recommended, so I gather this isn't a big
issue. Is there some specific use case where you find this useful?
 
A

Alexandru Popescu

#: Gavin Kistner changed the world a bit at a time by saying on 8/21/2005 7:29 PM :#
Sorry, I don't know Java (any more). Are you describing a global
function that is only available to instance methods of a certain
class, which is invoked without an explicit receiver?

Nope. I was talking about:
Code:
public class ExampleClass {
public static void staticMethod() {
// illegal access to any instance field
System.out.println("staticMethod");
}
}

ExampleClass.staticMethod(); // prints the message; no instance of
ExampleClass is available
ExampleClass ec= new ExampleClass();
ec.staticMethod(); // prints the message; not recommended but works[/QUOTE]

I don't know of a built-in mechanism to do this in Ruby, other than
something like:

class Foo
def self.staticMethod
puts "staticMethod"
end
def staticMethod
self.class.staticMethod
end
end

There are things you could do to make it easier to set this up, so
you might only have to type something like:
class Foo
static_method :foo {
# your_code_here
}
end
but that would just be a fancy interface to setting up a method on
both the class and its instances.


You say that it's not recommended, so I gather this isn't a big
issue. Is there some specific use case where you find this useful?
[/QUOTE]

Actually I was trying to clarify my mind. No, I am not gonna use such a thing (taking into account
that however it is wrong).

:alex |.::the_mindstorm::.|
 
D

David A. Black

Hi --

Sorry, I don't know Java (any more). Are you describing a global function
that is only available to instance methods of a certain class, which is
invoked without an explicit receiver?

Nope. I was talking about:
Code:
public class ExampleClass {
public static void staticMethod() {
// illegal access to any instance field
System.out.println("staticMethod");
}
}

ExampleClass.staticMethod(); // prints the message; no instance of
ExampleClass is available
ExampleClass ec= new ExampleClass();
ec.staticMethod(); // prints the message; not recommended but works[/QUOTE]

I don't know of a built-in mechanism to do this in Ruby, other than something
like:

class Foo
def self.staticMethod
puts "staticMethod"
end
def staticMethod
self.class.staticMethod
end
end[/QUOTE]

You could do:

class C
module M
def x
puts "'Static'?  Nothing is 'static' in Ruby :-)"
end
end

include M     # for instances of C
extend M      # for C itself
end

C.x
C.new.x


David
 
D

Devin Mullins

Here's another way:

class Object
alias_method :eek:rig_method_missing, :method_missing
def method_missing(*a,&b)
self.class.send *a,&b
end
end

class Class
def method_missing(*a,&b); orig_method_missing(*a,&b) end
end

"fun with Ruby".new #=>""
#w{can we say code smell?}.new #=>[]
"mwhaowt!".mwhaowt #=>NoMethodError

Devin
 

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

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top