This question has two parts.
In the Ruby Programming Language book, there is an example (section 8.1.1) of extending a string object and class with a module.
First question. Why is it that if you extend a class with a new method, and then create an object/instance of that class, you cannot access that method?
irb(main):001:0> module Greeter; def ciao; "Ciao!"; end; end
=> nil
irb(main):002:0> String.extend(Greeter)
=> String
irb(main):003:0> String.ciao
=> "Ciao!"
irb(main):004:0> x = "foo bar"
=> "foo bar"
irb(main):005:0> x.ciao
NoMethodError: undefined method `ciao' for "foo bar":String
from (irb):5
from :0
irb(main):006:0>
Second part, When I try to extend a Fixnum object, I get an undefined method error. Can someone explain why this works for a string but not a fixnum?
irb(main):045:0> module Greeter; def ciao; "Ciao!"; end; end
=> nil
irb(main):006:0> 3.extend(Greeter)
TypeError: can't define singleton
from (irb):6:in `extend_object'
from (irb):6:in `extend'
from (irb):6
The extends keyword extends a class (indicates that a class is inherited from another class). In Java, it is possible to inherit attributes and methods from one class to another. We group the "inheritance concept" into two categories: subclass (child) - the class that inherits from another class.
Extends: In Java, the extends keyword is used to indicate that the class which is being defined is derived from the base class using inheritance. So basically, extends keyword is used to extend the functionality of the parent class to the subclass.
A class can extend only one other class. To use the proper terminology, Java allows single inheritance of class implementation. Later in this chapter, we'll talk about interfaces, which take the place of multiple inheritance as it's primarily used in other languages. A subclass can be further subclassed.
A Java class can only extend one parent class. Multiple inheritance is not allowed. Interfaces are not classes, however, and an interface can extend more than one parent interface. The extends keyword is used once, and the parent interfaces are declared in a comma-separated list.
First question. Why is it that if you extend a class with a new method, and then create an object/instance of that class, you cannot access that method?
Because you extended the String class, so #ciao is a class method and not an instance method.
String.send(:include, Greeter)
x = "foo bar"
x.ciao
# => "Ciao!"
Second part, When I try to extend a Fixnum object, I get an undefined method error. Can someone explain why this works for a string but not a fixnum?
Here's the short answer.
"Fixnums, Symbols, true, nil, and false are implemented as immediate values. With immediate values, variables hold the objects themselves, rather than references to them.
Singleton methods cannot be defined for such objects. Two Fixnums of the same value always represent the same object instance, so (for example) instance variables for the Fixnum with the value "one" are shared between all the "ones" is the system. This makes it impossible to define a singleton method for just one of these."
Off course, you can include/exten the Fixnum class and every Fixnum instance will expose the methods in the Mixin. This is exactly what Rails/ActiveSupport does in order to allow you to write
3.days.ago
1.hour.from_now
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With