I am familiar with the concept of nesting classes and modules within another module and grouping them in a namespace. What is the idea / purpose behind
Nesting classes within another class
class A
class B
def method_B
...
end
end
end
Nesting modules within another class
class A
module c
def method_c
...
end
end
end
thanks,
ash
Classes are also namespaces, so it's the same idea. Class is a subclass of Module, so if you get it in the context of modules, you also get it in the context of classes.
It is all about grouping related concerns while exposing sensible semantics. As an example of number 1 an HTTP::Request (Request class embedded in a larger HTTP protocol class) is a quite different thing from an FTP::Request. With modules it enables the common ruby idiom of Behavior::InstanceMethods and Behavior::ClassMethods for handling mixins.
Related
I'm reading my ruby book. Looking at the code below,
module Destroy
def destroy(anyObject)
#anyObject = anyObject
puts "I will destroy the object: #{anyObject}"
end
end
class User
include Destroy
attr_accessor :name, :email
def initialize(name,email)
#name = name
#email = email
end
end
my_info = User.new("Bob","Bob#example.com")
puts "So your name is: #{my_info.name} and you have email #{my_info.email}"
user = User.new("john","john#example.com")
user.destroy("blah")
I could've just created another method inside my class. Why would I want to do this? Why would I want to use a module? It's not like embedding this into other classes is any easier than just using normal inheritance.
You can think of a module and the methods and constants inside of it as more of providing utility functions and actions that you can include to other objects as you see fit. For example, if you wanted to use destroy function in the objects Foo and Bar you would do similarly:
class Foo
include Destroy
# other code below
end
class Bar
include Destroy
# other code below
end
Now any Foo or Bar object has access to all the methods or constants inside of destroy.
Modules define a namespace, a sandbox in which your methods and constants can play without having to worry about being stepped on by other methods and constants. The ruby docs goes into more depth about this and includes a good example practical of when you would want to use it as seen below:
module Debug
def whoAmI?
"#{self.type.name} (\##{self.id}): #{self.to_s}"
end
end
class Phonograph
include Debug
# ...
end
class EightTrack
include Debug
# ...
end
ph = Phonograph.new("West End Blues")
et = EightTrack.new("Surrealistic Pillow")
ph.whoAmI? » "Phonograph (#537766170): West End Blues"
et.whoAmI? » "EightTrack (#537765860): Surrealistic Pillow"
In this example, every class that includes Debug has access to the method whoAmI? and other methods and constants that Debug includes without having to redefine it for every class.
Some programming languages such as C++, Perl, and Python allow one class to inherit from multiple other classes; that is called multiple inheritance. Ruby does not support multiple inheritance. That means each class can only inherit from one other class. However, there are cases where a class would benefit by acquiring methods defined within multiple other classes. That is made possible by using a construct called module.
A module is somewhat similar to a class, except it does not support inheritance, nor instantiating. It is mostly used as a container for storing multiple methods. One way to use a module is to employ an include or extend statement within a class. That way, the class gains access to all methods and objects defined within the module. It is said that the module is mixed in the class. So, a mixin is just a module included in a class. A single module can be mixed in multiple classes, and a single class can mix in multiple modules; thus, any limitations imposed by Ruby's single inheritance model are eliminated by the mixin feature.
Modules can also be used for namespacing. That is explained in this post at the Practicing Ruby website.
You are writing a module in the same file as the class, but not necessarily inside the class, but anyway.
For me there are 3 reasons to use a module(more details here):
Modules provide a namespace and prevent name clashes.
Modules implement the mixin facility.
When you have a very complex and dense class, you can split it into
modules and include them into the main class.
Your example is fairly simple, it would indeed make more sense to write the method in the class itself, but try to imagine a complex scenario.
Multiple inheritance in Ruby is simulated by including modules, but it's not possible to inherit properties directly from modules (that are not classes). The solution I came up was to define properties on the module initialization (code below). Is there a better way to achieve multiple inheritance compared the code below (inheriting methods AND properties)?
module MyCustomMixin
attr_accessor :a
def initialize
self.a = 1
end
def b
"something"
end
end
class MyCreateView < CreateView
include MyCustomMixin
end
class MyReadView < ReadView
include MyCustomMixin
end
class MyUpdateView < UpdateView
include MyCustomMixin
end
class MyDeleteView < DeleteView
include MyCustomMixin
end
The thing is, this is technically doable, but it requires a bit of finagling that doesn't look very pretty (especially with #initialize) - and rightfully so. I wouldn't recommend writing code in this way if the only purpose is to prevent code repetition.
So, consider:
What's the reason for having a MyFooView version for every FooView? Is it just to include mixins?
Perhaps all the Views have a common parent to which you could add this mixin?
Does the mixin contain functionality that is used in things other than View? Why not just add it directly to the parent View?
If the mixin is really that independent of the View classes, why isn't it just a class in itself, so that each View would own an instance of it?
I am new to Ruby but have been looking through some source code. I came across the kind of structures shown below in some source code (names of modules, classes not the real ones)
module ModuleOne
class MyClass
module CommonModule
# code ....
end # module CommonModule
end # class MyClass
end # module ModuleOne
or this example
module ModuleOne
class MyClass
class MyClassTwo
#code ............
end #class MyClassTwo
end #class MyClass
end #module ModuleOne
From my reading so far I know about wrapping classes in modules, but I haven't heard of the kinds of wrapping (modules inside modules or classes in classes for example) shown above. Can I ask,
1. Is this good practice and commonly done ?
2. What is the advantage of structuring code in this way ?
Thanks for any comments or pointers
Dave
Nesting is done to encapsule constants, which modules are special cases of. In other words, they are used for namespacing. When you want a particular module to be accessible only within the context of a certain module, you should do nesting. By doing so, that module will not be accessible by default from outside; you would have to prefix the namespace to do so. When you have too many layers of nesting, or when the module body is long, it would become hard to follow it in the code, so a good way in such case is to write the whole namespace.
module ModuleOne
...
end
class ModuleOne::MyClass
...
end
class ModuleOne::MyClass::MyClassTwo
...
end
In Ruby, one can declare classes like
class A
class B
end
end
and then instantiate the inner class like A::B.new.
Does B have some sort of special relationship with A (as is the case in Java) or is A just its namespace? In other words, is nesting a class in a class the same as nesting it in a module?
This is one of those times when you should really just fire up irb and try it.
Yes, a class can be defined within another class. Since a class's superclass is Module (i.e. Class extends Module), they can do almost everything a Module can. A notable exception is that you cannot include (mixin) a class.
That said, there's very little reason to actually use this design pattern. It is more likely that A and B can be considered siblings. There is no need to arbitrarily namespace until you are blue in the face. If you are more than 3 levels deep, stop and consider refactoring.
A better design pattern for this example might be:
module Alphabet
class A; end
class B; end
end
For something more complicated, this continues to work nicely using Mixins:
module Animals
class Dog
include Walking
end
module Walking
# some methods pertaining to the ability to walk
end
end
Yes, it's essentially the same as nesting in module. Nested class does not have any kind of special relationship to the class it's nested in.
Yes and...no. A Module can't be instantiated whereas a class can, so there is a difference in nesting a class within a Module vs. using a class nested within a class.
For example: You cannot instantiate an object of Ford here (i.e. Cobra, F-150, Mustang, etc.) because you cannot instantiate a module,.
`module Ford
class Engine
...
end
end`
But you can have an instance of the class Ford as well as instances of Ford engines with using nested classes like so:
`class Ford
class Engine
##actions = ['list', 'find', 'add', 'quit']
def self.actions; ##actions; end
end
def self.truck_exists?
#Some more stuff here
end
end`
Classes (and Modules) have different usages:
Namespace: when you define a class (or module) inside another class (or module), you have to use a different notation outside the defining class to reach the inner class or module.
Template for instances: There modules and classes behave totally (well mostly) different.
Inheritance: You may extend a class, so you inherit all its attributes and methods, which works for modules as well. Or you may include a module (not: a class) to add its methods (and attributes) to your scope. Ruby plays here tricks by mixin the module in the class hierarchy.
So in the context of using name spaces, they are the same. However I would all the time use modules (only), but that is more a matter of style. The best book on this topic is in my opinion "Metaprogramming Ruby" by Paolo Perrotta.
In Ruby, since you can include multiple mixins but only extend one class, it seems like mixins would be preferred over inheritance.
My question: if you're writing code which must be extended/included to be useful, why would you ever make it a class? Or put another way, why wouldn't you always make it a module?
I can only think of one reason why you'd want a class, and that is if you need to instantiate the class. In the case of ActiveRecord::Base, however, you never instantiate it directly. So shouldn't it have been a module instead?
I just read about this topic in The Well-Grounded Rubyist (great book, by the way). The author does a better job of explaining than I would so I'll quote him:
No single rule or formula always results in the right design. But it’s useful to keep a
couple of considerations in mind when you’re making class-versus-module decisions:
Modules don’t have instances. It follows that entities or things are generally best
modeled in classes, and characteristics or properties of entities or things are
best encapsulated in modules. Correspondingly, as noted in section 4.1.1, class
names tend to be nouns, whereas module names are often adjectives (Stack
versus Stacklike).
A class can have only one superclass, but it can mix in as many modules as it wants. If
you’re using inheritance, give priority to creating a sensible superclass/subclass
relationship. Don’t use up a class’s one and only superclass relationship to
endow the class with what might turn out to be just one of several sets of characteristics.
Summing up these rules in one example, here is what you should not do:
module Vehicle
...
class SelfPropelling
...
class Truck < SelfPropelling
include Vehicle
...
Rather, you should do this:
module SelfPropelling
...
class Vehicle
include SelfPropelling
...
class Truck < Vehicle
...
The second version models the entities and properties much more neatly. Truck
descends from Vehicle (which makes sense), whereas SelfPropelling is a characteristic of vehicles (at least, all those we care about in this model of the world)—a characteristic that is passed on to trucks by virtue of Truck being a descendant, or specialized
form, of Vehicle.
I think mixins are a great idea, but there's another problem here that nobody has mentioned: namespace collisions. Consider:
module A
HELLO = "hi"
def sayhi
puts HELLO
end
end
module B
HELLO = "you stink"
def sayhi
puts HELLO
end
end
class C
include A
include B
end
c = C.new
c.sayhi
Which one wins? In Ruby, it turns out the be the latter, module B, because you included it after module A. Now, it's easy to avoid this problem: make sure all of module A and module B's constants and methods are in unlikely namespaces. The problem is that the compiler doesn't warn you at all when collisions happen.
I argue that this behavior does not scale to large teams of programmers-- you shouldn't assume that the person implementing class C knows about every name in scope. Ruby will even let you override a constant or method of a different type. I'm not sure that could ever be considered correct behavior.
My take: Modules are for sharing behavior, while classes are for modeling relationships between objects. You technically could just make everything an instance of Object and mix in whatever modules you want to get the desired set of behaviors, but that would be a poor, haphazard and rather unreadable design.
The answer to your question is largely contextual. Distilling pubb's observation, the choice is primarily driven by the domain under consideration.
And yes, ActiveRecord should have been included rather than extended by a subclass. Another ORM - datamapper - precisely achieves that!
I like Andy Gaskell's answer very much - just wanted to add that yes, ActiveRecord should not use inheritance, but rather include a module to add the behavior (mostly persistence) to a model/class. ActiveRecord is simply using the wrong paradigm.
For the same reason, I very much like MongoId over MongoMapper, because it leaves the developer the chance to use inheritance as a way of modelling something meaningful in the problem domain.
It's sad that pretty much nobody in the Rails community is using "Ruby inheritance" the way it's supposed to be used - to define class hierarchies, not just to add behavior.
The best way I understand mixins are as virtual classes. Mixins are "virtual classes" that have been injected in a class's or module's ancestor chain.
When we use "include" and pass it a module, it adds the module to the ancestor chain right before the class that we are inheriting from:
class Parent
end
module M
end
class Child < Parent
include M
end
Child.ancestors
=> [Child, M, Parent, Object ...
Every object in Ruby also has a singleton class. Methods added to this singleton class can be directly called on the object and so they act as "class" methods. When we use "extend" on an object and pass the object a module, we are adding the methods of the module to the singleton class of the object:
module M
def m
puts 'm'
end
end
class Test
end
Test.extend M
Test.m
We can access the singleton class with the singleton_class method:
Test.singleton_class.ancestors
=> [#<Class:Test>, M, #<Class:Object>, ...
Ruby provides some hooks for modules when they are being mixed into classes/modules. included is a hook method provided by Ruby which gets called whenever you include a module in some module or class. Just like included, there is an associated extended hook for extend. It will be called when a module is extended by another module or class.
module M
def self.included(target)
puts "included into #{target}"
end
def self.extended(target)
puts "extended into #{target}"
end
end
class MyClass
include M
end
class MyClass2
extend M
end
This creates an interesting pattern that developers could use:
module M
def self.included(target)
target.send(:include, InstanceMethods)
target.extend ClassMethods
target.class_eval do
a_class_method
end
end
module InstanceMethods
def an_instance_method
end
end
module ClassMethods
def a_class_method
puts "a_class_method called"
end
end
end
class MyClass
include M
# a_class_method called
end
As you can see, this single module is adding instance methods, "class" methods, and acting directly on the target class (calling a_class_method() in this case).
ActiveSupport::Concern encapsulates this pattern. Here's the same module rewritten to use ActiveSupport::Concern:
module M
extend ActiveSupport::Concern
included do
a_class_method
end
def an_instance_method
end
module ClassMethods
def a_class_method
puts "a_class_method called"
end
end
end
Right now, I'm thinking about the template design pattern. It just wouldn't feel right with a module.