mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38701 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1da85070b0
commit
a13aee62d2
3 changed files with 297 additions and 30 deletions
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
288
doc/syntax/modules_and_classes.rdoc
Normal file
288
doc/syntax/modules_and_classes.rdoc
Normal file
|
@ -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.
|
||||
|
Loading…
Reference in a new issue