summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--doc/syntax/methods.rdoc32
-rw-r--r--doc/syntax/modules_and_classes.rdoc288
3 files changed, 297 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index 0a67b7e5f3..27886dc9a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sat Jan 5 10:21:54 2013 Eric Hodel <drbrain@segment7.net>
+
+ * doc/syntax/modules_and_classes.rdoc: Added documentation of syntax
+ for Modules and Classes.
+ * doc/syntax/methods.rdoc: Moved some text to the Modules and
+ Classes syntax document.
+
Sat Jan 5 08:38:27 2013 Eric Hodel <drbrain@segment7.net>
* doc/syntax/methods.rdoc: Added return values and scope sections,
diff --git a/doc/syntax/methods.rdoc b/doc/syntax/methods.rdoc
index b3233e647a..832ba269b0 100644
--- a/doc/syntax/methods.rdoc
+++ b/doc/syntax/methods.rdoc
@@ -38,7 +38,7 @@ The standard syntax to define a method:
# ...
end
-add the method to a class. You can define an instance method on a specific
+adds the method to a class. You can define an instance method on a specific
class with the +class+ keyword:
class C
@@ -47,24 +47,6 @@ class with the +class+ keyword:
end
end
-In many languages, the +class+ keyword lets the compiler know that you're
-creating a class. This is true in Ruby, too, the first time you use the
-_class_ keyword: when it sees that you're _opening_ a class for
-the first time, it creates it. When you open a class that already exists, Ruby
-enables to you _extend_ it with new methods. You can even extend core
-classes:
-
- class String
- def hello
- "Hello, world!"
- end
- end
-
- "".hello # returns "Hello, world!"
-
-However, This is somewhat risky due to namespace pollution so this ability is
-best used sparingly.
-
A method may be defined on another object. You may define a "class method" (a
method that is defined on the class, not an instance of the class) like this:
@@ -74,16 +56,6 @@ method that is defined on the class, not an instance of the class) like this:
end
end
-or a more concrete example:
-
- class String
- def self.hello
- "Hello, world!"
- end
- end
-
- String.hello # returns "Hello, world!"
-
However, this is simply a special case of a greater syntactical power in Ruby,
the ability to add methods to any object. Classes are objects, so adding
class methods is simply adding methods to the Class object.
@@ -98,7 +70,7 @@ The syntax for adding a method to an object is as follows:
greeting.broaden # returns "Hello, world!"
-_self_ is a keyword referring to the current object under consideration
++self+ is a keyword referring to the current object under consideration
by the compiler, which might make the use of +self+ in defining a class
method above a little clearer. Indeed, the example of adding a +hello+
method to the class +String+ can be rewritten thus:
diff --git a/doc/syntax/modules_and_classes.rdoc b/doc/syntax/modules_and_classes.rdoc
new file mode 100644
index 0000000000..4710dcf3cb
--- /dev/null
+++ b/doc/syntax/modules_and_classes.rdoc
@@ -0,0 +1,288 @@
+= Modules
+
+Modules serve two purposes in Ruby, namespacing and mix-in functionality.
+
+A namespace can be used to organize code by package or functionality that
+separates common names from interference by other packages. For example, the
+Curses namespace provides functionality for curses that prevents a collision
+for the common name "Window".
+
+Mix-in functionality allows sharing common methods across multiple classes or
+modules. Ruby comes with the Enumerable mix-in module which provides many
+enumeration methods based on the +each+ method and Comparable allows comparison
+of objects based on the <code><=></code> comparison method.
+
+Note that there are many similarities between modules and classes. Besides the
+ability to mix-in a module, the description of modules below also applies to
+classes.
+
+== Module Definition
+
+A module is created using the +module+ keyword:
+
+ module MyModule
+ # ...
+ end
+
+A module may be reopened any number of times to add, change or remove
+functionality:
+
+ module MyModule
+ def my_method
+ end
+ end
+
+ module MyModule
+ alias my_alias my_method
+ end
+
+ module MyModule
+ remove_method :my_method
+ end
+
+Reopening classes is a very powerful feature of Ruby, but it is best to only
+reopen classes you own. Reopening classes you do not own may lead to naming
+conflicts or difficult to diagnose bugs.
+
+== Nesting
+
+Modules may be nested:
+
+ module Outer
+ module Inner
+ end
+ end
+
+Many packages create a single outermost module (or class) to provide a
+namespace for their functionality.
+
+You may also define inner modules using <code>::</code> provided the outer
+modules (or classes) are already defined:
+
+ module Outer::Inner::GrandChild
+ end
+
+Note that this will raise a +NameError+ if +Outer+ and
+<code>Outer::Inner</code> are not already defined.
+
+This style has the benefit of allowing the author to reduce the amount
+of indentation. Instead of 3 levels of indentation only one is necessary.
+However, the scope of constant lookup is different for creating a namespace
+using this syntax instead of the more verbose syntax.
+
+== Scope
+
+=== +self+
+
++self+ refers to the object that defines the current scope. +self+ will change
+when entering a different method or when defining a new module.
+
+=== Constants
+
+Accessible constants are different depending on the module nesting (which
+syntax was used to define the module). In the following example
+the constant <code>A::Z</code> is accessible from B as A is part of the
+nesting:
+
+ module A
+ Z = 1
+
+ module B
+ p Module.nesting #=> [A::B, A]
+ p Z #=> 1
+ end
+ end
+
+However, if you use <code>::</code> to define <code>A::B</code> without nesting
+it inside +A+ a NameError exception will be raised because the nesting does not include +A+:
+
+ module A
+ Z = 1
+ end
+
+ module A::B
+ p Module.nesting #=> [A::B]
+ p Z #=> raises NameError
+ end
+
+If a constant is defined at the top-level you may preceded it with
+<code>::</code> to reference it:
+
+ Z = 0
+
+ module A
+ Z = 1
+
+ module B
+ p ::Z #=> 0
+ end
+ end
+
+=== Methods
+
+Class methods (also known as module functions, see Module#module_function) may
+be called directly.
+
+When a class method references a constant it uses the same rules as referencing
+it outside the method as the scope is the same.
+
+Instance methods defined in a module are only callable when included. These
+methods have access to the constants defined when they were included through
+the ancestors list:
+
+ module A
+ Z = 1
+
+ def z
+ Z
+ end
+ end
+
+ include A
+
+ p self.class.ancestors #=> [Object, A, Kernel, BasicObject]
+ p z #=> 1
+
+=== Visibility
+
+Ruby has three types of visibility. The default is +public+. A public method
+may be called from any other object.
+
+The second visibility is +protected+. When calling a protected method the
+sender must be a subclass of the receiver or the receiver must be a subclass of
+the sender. Otherwise a NoMethodError will be raised.
+
+Protected visibility is most frequently used to define <code>==</code> and
+other comparison methods where the author does not wish to expose an object's
+state to any caller and would like to restrict it only to inherited classes.
+
+Here is an example:
+
+ class A
+ def n(other)
+ other.m
+ end
+ end
+
+ class B < A
+ def m
+ 1
+ end
+
+ protected :m
+
+ end
+
+ class C < B
+ end
+
+ a = A.new
+ b = B.new
+ c = C.new
+
+ c.n b #=> 1 -- C is a subclass of B
+ b.n b #=> 1 -- m called on defining class
+ a.n b # raises NoMethodError A is not a subclass of B
+
+The third visibility is +private+. A private method may not be called with a
+receiver, not even +self+. If a private method is called with a receiver a
+NoMethodError will be raised.
+
+= Classes
+
+Every class is also a module, but unlike modules a class may not be mixed-in to
+another module (or class). Like a module, a class can be used as a namespace.
+A class also inherits methods and constants from its superclass.
+
+== Defining a class
+
+Use the +class+ keyword to create a class:
+
+ class MyClass
+ # ...
+ end
+
+If you do not supply a superclass your new class will inherit from Object. You
+may inherit from a different class using <code><</code> followed by a class
+name:
+
+ class MySubclass < MyClass
+ # ...
+ end
+
+There is a special class BasicObject which is designed as a blank class and
+includes a minimum of built-in methods. You can use BasicObject to create an
+independent inheritance structure. See the BasicObject documentation for
+further details.
+
+== Inheritance
+
+Any method defined on a class is callable from its subclass:
+
+ class A
+ Z = 1
+
+ def z
+ Z
+ end
+ end
+
+ class B < A
+ end
+
+ p B.new.z #=> 1
+
+The same is true for constants:
+
+ class A
+ Z = 1
+ end
+
+ class B < A
+ def z
+ Z
+ end
+ end
+
+ p B.new.z #=> 1
+
+You can override the functionality of a superclass method by redefining the
+method:
+
+ class A
+ def m
+ 1
+ end
+ end
+
+ class B < A
+ def m
+ 2
+ end
+ end
+
+ p B.new.m #=> 2
+
+If you wish to invoke the superclass functionality from a method use +super+:
+
+ class A
+ def m
+ 1
+ end
+ end
+
+ class B < A
+ def m
+ 2 + super
+ end
+ end
+
+ p B.new.m #=> 3
+
+When used without any arguments +super+ uses the arguments given to the
+subclass method. To send no arguments to the superclass method use
+<code>super()</code>. To send specific arguments to the superclass method
+provide them manually like <code>super(2)</code>.
+
++super+ may be called as many times as you like in the subclass method.
+