Include and extend Module - Ruby Way

(Alexandru Popescu) #1

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?
[/code]

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

(Paul) #2

It is a Class method so you'd go

ExtendModule::moduleMethod

module method

(Charles Steinman) #3

Alexandru Popescu wrote:

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.
[/quote]

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?

(Alexandru Popescu) #4

#: Charles Steinman changed the world a bit at a time by saying on 8/21/2005 9:51 AM :#

Alexandru Popescu wrote:

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.

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
[/code]

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.
[/quote]

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?

(Gavin Kistner) #5

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.

···

On Aug 21, 2005, at 3:11 AM, Alexandru Popescu wrote:

(Alexandru Popescu) #6

#: Gavin Kistner changed the world a bit at a time by saying on 8/21/2005 4:36 PM :#

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?

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

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.

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

···

On Aug 21, 2005, at 3:11 AM, Alexandru Popescu wrote:

(Gavin Kistner) #7

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?

···

On Aug 21, 2005, at 9:04 AM, Alexandru Popescu wrote:

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

(Alexandru Popescu) #8

#: Gavin Kistner changed the world a bit at a time by saying on 8/21/2005 7:29 PM :#

···

On Aug 21, 2005, at 9:04 AM, Alexandru Popescu wrote:

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

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?

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

(David A. Black) #9

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

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

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

···

On Mon, 22 Aug 2005, Gavin Kistner wrote:

On Aug 21, 2005, at 9:04 AM, Alexandru Popescu wrote:

--
David A. Black
dblack@wobblini.net

(Devin Mullins) #10

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

Here's another way:

class Object
alias_method :orig_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