Friday, November 16, 2007

R4R and PR2 environment top-level method 学习笔记

R4R
Defining a top-level method
Suppose you define a method at the top level:


def talk
puts "Hello"
end

Who, or what, does the method belong to? It’s not inside a class or module definition block, so it doesn’t appear to be an instance method of a class or module. It’s not attached to any particular object (as in def obj.talk), so it’s not a singleton method. What is it?
By special decree (this is just the way it works!), top-level methods are private instance methods of the Kernel module.
That decree tells you a lot.
Because top-level methods are private, you can’t call them with an explicit receiver; you can only call them by using the implied receiver, self. That means self must be an object on whose method search path the given top-level method lies.

The default object (self) and scope
But every object’s search path includes the Kernel module, because the class Object mixes in Kernel, and every object’s class has Object as an ancestor. That means you can always call any top-level method, wherever you are in your program.
It also means you can never use an explicit receiver on a top-level method.
To illustrate this, let’s extend the talk example. Here it is again, with some code that exercises it:

def talk
puts "Hello"
end
puts "Trying 'talk' with no receiver..."
talk
puts "Trying 'talk' with an explicit receiver..."
obj = Object.new
obj.talk

The first call to talk succeeds; the second fails, because you’re trying to call a private method with an explicit receiver.
The rules concerning definition and use of top-level methods brings us all the way back to some of the bareword methods we’ve been using since as early as chapter1(R4R book). You’re now in a position to understand exactly how those methods work.

Programming Ruby 2nd
Top-Level Execution Environment
Many times in this book we’ve claimed that everything in Ruby is an object. However, we’ve used one thing time and time again that appears to contradict this—the top-level Ruby execution environment.
puts "Hello, World"
Not an object in sight. We may as well be writing some variant of Fortran or BASIC.
But dig deeper, and you’ll come across objects and classes lurking in even the simplest code.
We know that the literal "Hello, World" generates a Ruby String, so that’s one object. We also know that the bare method call to puts is effectively the same as self.puts. But what is self?
self.class ! Object
At the top level, we’re executing code in the context of some predefined object. When we definemethods, we’re actually creating (private) instancemethods for class Object.
This is fairly subtle; as they are in class Object, these methods are available everywhere.
And because we’re in the context of Object, we can use all of Object’s methods (including those mixed-in from Kernel) in function form. This explains why we
can call Kernel methods such as puts at the top level (and indeed throughout Ruby): these methods are part of every object. Top-level instance variables also belong to this top-level object.

命令行中定义的其实是定义在Kernel中的私有方法,并被Mix-in到Object类中成为其对象私有实例方法。因为class Module (< Object)和class Class (< Module)这3者的继承关系,所以控制台里定义的方法在module和class实例对象中可以调用。

No comments :