Self in ruby, scope, use of visibility

Source: Internet
Author: User
Tags class definition constant instance method visibility

Some things mean nothing at any time, such as integers, and what you see is what it says. As with keywords, you can't use def,class these keywords as variable names, so when you see them, it's easy to know what they do. But there are a lot of things that are meant to depend on the situation they are in, which means that they may be different at different times.

Self represents the current or default object, and it represents a specific object each time the program runs. There will always be a self, but the things it represents will change.

The scope (scope) rule determines the visibility of the variable. You need to know which scope is affected by the location, so that you can understand which variables represent what, and not confuse them with variables of the same name in other scopes.

Know which scope you are currently in and know who the object that self represents, so that you can understand exactly what is happening before you quickly analyze the problem you are experiencing.

5:54 * * *

Self

6:07 * * *

Use the keyword self to get the current object. In a program run, there is and only one self. Self has some privileges, and we'll see it in a moment. There will always be only one current object or self. There are some rules about who is going to be self.

At the top of the Self object

The top meaning here is that it is outside of any class or module definition. For example, open a blank file and enter:

x = 1
So we create a local variable x at the top level, and the following code creates a method at the top level:

def m
End
Take a look at the top self who is, perform:

Puts self
The return is:

Main
Main is a special word, it means self itself, for example we can try this:

m = Self
Self in class, module definition

In class and module definitions, self refers to a class or module object.

The following experiment will tell you who the self is in the definition of the class and the definition of the module, and do an experiment:

Class C
Puts ' class: '
# Self is C
Puts self

Module M
Puts ' module: '
# Self is c::m
Puts self
End
Puts ' Back to class level: '
# Self is C again #
Puts self
End
After entering the definition area of a class or module, the class and the module object become self. The above example, at the beginning, self represents the object of class C. When you enter the area where the module is defined, self is c::m, which represents the nested module M within the C class. After returning to the definition of Class C, self represents the object again, that is, C.

Self in the definition instance method

Self is very microsecond in the definition of an instance method, because Ruby's interpreter, after encountering Def/end, immediately defines the method. The code in the method definition has not yet been executed. The way you see the on-screen definition, you only know that when the method is invoked, self is the object that invokes the method. At the time of defining the method, the most you can say is that self in this method will be the object of the calling method in the future.

Do an experiment:

Class C
def X
Puts "Class C, method x:"
Puts self
End
End

c = c.new
c.x
Puts "that is a called to X by: #{c}"
Will output:

Class C, Method x:
#<c:0x00000101b381a0>
That is a call to X by: #<c:0x00000101b381a0>
The output of this thing:#<c:0x00000101b381a0>, represents a C instance. When the X method is executed, self is the instance object C that invokes it.

Self in independent methods and class methods

When executing an independent method, self represents the object that owns the method.

The following experiment creates an object, defines an independent method in the object, and then calls the independent method to see who the self represents. Experiment:

obj = object.new
def Obj.show_me
Puts "Inside Singleton method Show_me of #{self}"
End

Obj.show_me
Puts "back from called to Show_me by #{obj}"
Will output:

Inside Singleton method Show_me of #<object:0x007fd189963428>
Back from call to Show_me by #<object:0x007fd189963428>
A class method is basically an independent method defined on a class object, and then an experiment:

Class C
def c.x
Puts "class method of Class C"
Puts "self: #{self}"
End
End
c.x
Will output:

class method of Class C
Self:c
Within the class we can use self to represent the name of the class:

Class C
def self.x
Puts "class method of Class C"
Puts "self: #{self}"
End
End
If we:

Class D < C
End
D.x
The output will be:

class method of Class C
Self:d
Self as the default message recipient

September 8, 2016

The calling method is to send the message to the object, like this:

Obj.talk
Ticket.venue
' ABC '. Capitalize
When invoking a method, if the recipient of the message is self, you can ignore the receiver and a bit, Ruby uses self as the default recipient, meaning that the message you send is sent to self. Like this:

Talk
Venue
Capitalize
If there is a variable called talk, there is a method called talk, call talk when only a talk, then the priority of the variable will be higher. In this case you can add self, like this: Self.talk, or with parentheses: talk (), when invoking the talk method.

Class C
def C.no_dot
Puts ' as long as self is C, you can invoke this method without a point '
End
No_dot
End

C.no_dot
When the first callback uses No_dot, there is no obvious recipient, and Ruby sees it, and it will judge what you mean:

Self.no_dot
In the example above, Self.no_dot is not the same thing as C.no_dot, because we are in the block of definition C, so self is c. The result is that the method is invoked, and then we see the output of the result.

The second time we used C.no_dot, it was already in the definition class block, so C is no longer self. That is, to call No_dot, we have to specify the recipient of the letter, which is C.

The result of this example output is two times the result of calling the No_dot method:

As long as self is C, you can call this method without a dot.
As long as self is C, you can call this method without a dot.
The most common way to use this method of no point invocation is when you invoke an instance method in another instance method, and then look at an example:

Class C
def X
Puts ' This is method X '
End

Def y
Puts ' This is the method y, I want to call X ' without dot '
X
End
End

c = c.new
C.y
The result of the output is:

This is the method y, I want to call x without dot
This is the method x
When the above call C.y, the method y is executed, and self refers to C (c is an instance of C). In Y, X is used, which is interpreted as information to be sent to self, so that the method x is executed.

There is a situation where you can't ignore the form of an object dot to invoke a method, that is, if the method's name has an equal sign (the Set method), that is, if you want to invoke the Venue= method on self, you need to do this: Self.venue = ' Town Hall ', not so: Venue = ' Town Hall '. Because Ruby will always think that identifier = value is assigning a value to a local variable.

Without a point method call, it is useful to use another method in one method, and then look at an example:

Class Person
Attr_accessor:first_name,: middle_name,: last_name

def whole_name
n = first_name + '
n << "#{middle_name}" if Middle_name
N << last_name
End
End

David = Person.new

David.first_name = ' David '
David.last_name = ' Black '

Puts "David's full name is: #{david.whole_name}"

David.middle_name = ' Alan '
Puts "David's full name is now: #{david.whole_name}"
The results of the output will be:

David's full name is: David Black.
David's full name is now: David Alan Black.
Interpreting instance variables by self

In a Ruby program, any instance variable will belong to the current object.

Let's do an experiment and see what the following things will output:

Class C
def Show_var
@v = ' I am ' instance variable initialized to a string. '
Puts @v
End
@v = "Instance variables can appear anywhere ..."
End

C.new.show_var
Will output:

I am A instance variable initialized to a string.
In the code above, there are two @v, one within the method definition and the other outside the method definition, and there is no connection between them. They are also instance variables, and the names are @v, but they are not the same variable and they belong to different objects.

The first occurrence of the @v is in the method definition block, that is, an instance method inside the C class, so that each instance object of Class C has its own instance variable @v.

The second occurrence of the @v belongs to the class C object. The class itself is also an object.

Every instance variable belongs to whatever object was playing the role of self at the moment the code containing the Insta NCE variable is executed.
Re-write the above example:

Class C
Puts "* Class definition block"
Puts "| ---Self is: #{self} "
@v = ' I am @v '
Puts "| ---#{@v} instance variable, belonging to: #{self} \ n '

def Show_var
Puts "* Instance method definition block"
Puts "| ---Self is: #{self} "
Puts "| ---@v instance variable belongs to: #{self} "
Print "| The value of the---@v is: "
P @v
End
End

c = c.new
C.show_var
The result of executing code output is:

* Class definition Block
| ---self is: C
| ---I am @v instance variable, belong to: C

* Instance method definition block
| ---self is:#<c:0x007fd3c8961f10>.
| ---@v instance variable belongs to:#<c:0x007fd3c8961f10>
| The value of the---@v is: nil
Scope

11:15 * * *

The scope refers to the visibility of identifiers, especially variables and constants. Different types of identifiers have different scoping rules. Using a variable x of the same name in two methods, $x with global variables in two places, will have different results. Because the local scope is not the same as the global variable.

Global scope and global variables

The global scope covers the entire program. Global variables are global scopes, and you can use them everywhere. Even if you turn on the definition of a new class or method, or the identity of self changes, the initial global variable is still available.

In the following example, you can use the initialized global variable in the body of the definition class:

$gvar = "I am a global variable"
Class C
def Examine_global
Puts $gvar
End
End

c = c.new
C.examine_global
The results of the output will be:

I'm a global variable.
Local scope

Class,module,def will create a new local scope.

Do an experiment:

Class C
A = 1

def local_a
A = 2
Puts a
End

Puts a
End

c = c.new
C.local_a
The result of the output is:

1
2
The first occurrence of the local variable A is under the local scope defined by the class. The second occurrence of a is under the local scope of the method definition. When the method definition is finished, the local scope returns to the class block, where the output of a is the local variable a declared below the local scope of the class block, and its value is 1. We then created an instance of the class, calling its Local_a method, which outputs the value of the local variable A, declared below the scope of the method definition, which is 2.

When you nest classes and modules, a new local scope is created each time a new definition block is encountered.

Try again:

Class C
A = 5

Module M
A = 4

Module N
A = 3

Class D
A = 2

def show_a
A = 1
Puts a
End
Puts a
End
Puts a
End
Puts a
End
Puts a
End

D = c::m::n::D. New
D.show_a
The results of the output will be:

2
3
4
5
1
Any class,module or method will open a new local scope, and each scope can have its own new local variables.

Local scope and self

Let's take a look at an example:

Class C
def x (value_for_a, Recurse=false)
A = Value_for_a
Print "Now Self is:"
P Self
Puts "Now A is:"
Puts a
If recurse
Puts "\ n Call yourself ..."
X ("Second value of a")
Puts "after calling itself over, A is:"
Puts a
End
End
End

c = c.new
C.x ("A's first value", true)
The results of the run will be:

Now Self is: #<c:0x007fa5fa162388>
Now A is:
The first value of a

Call yourself ...
Now Self is: #<c:0x007fa5fa162388>
Now A is:
The second value of a
After calling itself over, A is:
The first value of a
The instance method c#x has two parameters, the first parameter is the value to assign to the variable A, and the second parameter is a tag that indicates whether to call itself. The first line of the method initializes a local variable A, and the following lines of code are a string that prints the value of self and a.

Then it's time to make a decision (if recurse) and call yourself not to call yourself, which will be determined by the recurse variable. If you call yourself, method X is called, and the value of the Recurse parameter is not specified when invoked, and the default value of this parameter is false, so calling it itself will not continue to call itself.

When you call yourself, you set a different value for the value_for_a parameter ("a second value"), which means that you will output different information at the time of the call. But after we call ourselves back, we find that the value of a in the run X has not changed (or "A's first value"). That is, every time we call X, a new local scope is generated, even if self does not change.

Scope of constants

1:06 * * *

Constants can be defined in class and method definition blocks. If you know the nesting used in the definition, you can access the constants anywhere. Take a look at an example:

Module M
Class C
Class D
Module N
X = 1
End
End
End
End
For example, I want to access the constant X defined in module N, do this:

M::C::D:: n::x
The position of the constant can also be relative, and the following example validates this assertion:

Module M
Class C
Class D
Module N
X = 1
End
End
Puts D::n::x
End
End
In class C, you get the X in module N, which is d::n::x.

Sometimes you don't want to use a relative path to get a constant. For example, the class we want to create is the same as the class name built into Ruby, for example, there is a string class in Ruby, and if you create a violin (violin), there may be a string (string) inside. Like this:

Class violin
Class String
Attr_accessor:p Itch
def initialize (pitch)
@pitch = Pitch
End
End

DEF initialize
@e = string.new ("e")
@a = String.new ("a")
... etc...
Using string above refers to our own defined string class, and if you want to use the string class built into Ruby, you can use the constant delimiter (::, two colons), like this:

:: String.new (' Hello ')
Class variables, scopes, visibility

1:50 * * *

Class variables are used to maintain class states, whose names begin with two @ symbols, such as the @ @var. Class variables are not class scopes, they are class-level scopes. Class variables provide a mechanism for sharing data between classes and instance objects of a class, that is, class variables are visible on class method definitions and instance method definitions, and sometimes on top-level class definitions. In addition, class variables are not visible on other objects.

For example, first use the class method Car.add_make (make) to register the car wash manufacturer, and then use Car.new (make) to build a few cars:

Car.add_make ("Honda")
Car.add_make ("Ford")

h = car.new ("Honda")
f = car.new ("Ford")
H2 = Car.new ("Honda")
The program will tell you to create the car:

Create a new honda!
Create a new ford!
Create a new honda!
2:08 * *

2:27 * *

How many H2 did the same car manufacturer produce? We will use the instance method make_mates to find:

Puts "count the number of H2 cars ..."
Puts "There are #{h2.make_mates}"
How many cars are there? It takes a class instead of each individual car, so we can ask the class:

Puts "counting the total number of cars ..."
Puts "There are #{car.total_count}"
The output should be:

Count the total number of cars ...
A total of 3 vehicles.
Try to create a car without a car manufacturer:

x = Car.new ("Brand x")
Will complain:

Car.rb:21:in ' Initialize ': No such Make:brand X. (runtimeerror)
The code is as follows:

Class car
@ @makes = []
@ @cars = {}
@ @total_count = 0
Attr_reader:make
def Self.total_count
@ @total_count
End

def self.add_make (make)
Unless @ @makes. include? (make)
@ @makes << Make
@ @cars [Make] = 0
End
End

def initialize (make)
If @ @makes. include? (make)
Puts "creating a new car manufacturer: #{make}"
@make = Make
@ @cars [make] + + 1
@ @total_count + 1
Else
Raise "no car manufacturer: #{make}"
End
End

def make_mates
@ @cars [Self.make]
End
End
Three class variables are defined at the top of the class. @ @makes is an array that stores the name of the car manufacturer. @ @cars is a hash, which is the data of the name value pair type. @ @cars The name of the data is the car manufacturer car, the corresponding data is the number of cars. @ @total_count Stores the total number of cars produced.

There is also a make-readable property in the car class that has to be set to the value of the Make property when you create it. There is no writable property about the car manufacturer, because we do not want the class code to change the existing car manufacturer.

To access the @ @total_count class variable, the car class also defines a Total_count method that returns the current value of the class variable. Another class method is Add_make, which receives a parameter that places the value of the parameter in an array representing the car manufacturer with the << operator. In this way, we have to make sure that the added car manufacturer does not exist, and if it does not exist, put it in the car manufacturer's class variable @ @makes, and also set the @ @cars so that the car manufacturer's car is equal to zero. It means that there is no car produced by this car manufacturer.

Then came the Initialize method, where the new car was created. Every new car needs a car manufacturer, and if the car manufacturer doesn't exist, it's not in the @ @makes array, it triggers an error. If a car manufacturer exists, we will set the appropriate value for the car's Make property, increase the number of cars produced by the car manufacturer by one (@ @cars), and increase the total number of cars produced (@ @total_count).

There is also a make_mates method that can return all the cars produced by a certain car manufacturer.

Note the above in the Initialize method, and in the class method, such as Car.total_count,car.add_make above, all use the class variable. The instance method inside the class is initialize, and the class method is under different scopes. But they belong to the same class, so you can use class variables to share data between them.

class variables and class hierarchies

As we have said before, class variables use not a class scope, but also a class-level scope. Look at an example:

Class Parent
@ @value = 100
End

Class Child < Parent
@ @value = 200
End

Class Parent
Puts @ @value
End
The result of the output would be 200. The child is a subclass of parent, which is that parent shares the same class variables as the children. When you set the @ @value in the child, you set the only @ @value on the Parent and child.

3:17 * * *

Method access rules

3:18 * * *

Now that we know that Ruby programs send messages to objects, the main thing that the object does is respond to that information. Sometimes, objects want to be able to send themselves messages, but don't want others to send them messages. In this case, we can make the method private.

There are several access levels, private (private), protection (protected), public (publicly). Public is the default access level, and most of the information that is sent to an object is called a method with a publicly accessible level.

Private method

Think of the object as someone you ask him to do, like you want someone to bake a cake for you, to bake the cake for you, and the person who bakes the cake will do a series of tasks, such as playing an egg, and a face or something. People who bake cakes do these things, but he may not want to respond to all of them. All you ask is "Please bake a cake". Leave the rest to the pie maker.

Using code to simulate, create a file name is BAKER.RB, the code is as follows:

Class Cake
def initialize (batter)
@batter = Batter
@baked = True
End
End

Class Egg
End

Class flour
End

Class Baker
def Bake_cake
@batter = []
Pour_flour
Add_egg
Stir_batter
Return Cake.new (@batter)
End

def Add_egg
@batter. Push (Egg.new)
End

def Stir_batter
End

Private:p Our_flour,: Add_egg, Stir_batter
End
It uses a private method, and you can tell it the name you want to become a private method. Without arguments, it is like a switch, and all of the instance methods defined below will be private until the call is public or protected.

You can't:

b = baker.new
B.add_egg
This calls the Add_egg to make an error:

' <main> ': Private method ' Add_egg ' called for #<baker:0x00000002aeae50> (Nomethoderror)
Since Add_egg is a private method, you are not allowed to specify a specific receiving object when calling it.

If we do not add information to the recipient:

Add_egg
Can you call this method alone? Where will the information be sent? If no object processes information, how is the method invoked? When calling a method, if you do not specify the recipient of the message, Ruby sends the information to the current object, which is the object that self represents.

You can infer that the object that can respond to add_egg this information can only be the object that self represents that can respond to Add_egg. That is, we can only invoke the instance method of Add_egg when self is the instance of Baker.

Private methods and independent methods

Private methods are not the same as independent methods. Independent methods belong to only one object. Private methods can belong to more than one object, but are invoked only in the correct case. It is not the object that you send the message to, but the object that self represents when you send the message.

Protection methods

The protection method is a gentle point private method. The rules are like this:

You can call a protected to "an object X, as long as the" default object (self) is a instance of the same class as X A ancestor or descendant class of X ' s class.
The main purpose of the protection method is that you can use another instance of this class to do something on one instance of a class. Take a look at an example:

Class C
Def initialize (n)
@n = n
End

def N
@n
End

def compare (c)
If C.N > N
Puts "N larger for another object"
Else
Puts "Another object's N or smaller"
End
End

Protected:n
End

C1 = c.new (100)
C2 = c.new (101)
C1.compare (C2)
The example above is to compare an instance of class C with another instance of it. This comparison relies on the result returned by invoking method N. The object to compare (an example of a C1 object) needs to have another object (C2) perform its N method. That is, n cannot be a private method.

This requires the use of a protection method. Let n be the protection method, not the private method, C1 can let C2 to execute method N, because C1 and C2 are instance objects of the same class. But if you try to call the N method above the C object, it will fail because C is not an instance of Class C.

Subclasses also inherit method access rules on super classes, but you can override these rules in subclasses.

4:35 * * *

Top methods

4:35 * * *

The most natural thing to do with Ruby is to design classes, modules, and instantiate classes. But sometimes you want to write scripts quickly and don't want to put the code in a class, you can define and use these methods at the top level (top-level). The thing to do is to write code in the top-level default object called Main, which is an instance of an automatically generated object, mainly because there has to be a thing that is self, even at the top.

Defining Top methods

Define a method at the top level:

Def talk
Puts ' Hello '
End
A method defined at the top level acts as a private method on an instance of the Object class. The code above is equivalent to:

Class Object
Private

Def talk
Puts ' Hello '
End
End
These methods must be invoked using the naked word style, which means that the recipients of the information cannot be specified because they are private methods. The private instance method of object can be invoked anywhere, because object is found in the path of the method it belongs to, so the top-level method is always valid.

Let's look at an example:

Def talk
Puts ' Hello '
End

Puts "Execute Talk without recipient"
Talk
Puts "Add a recipient to execute talk"
obj = object.new
Obj.talk
The first execution of the talk succeeds, and the second executes with an error, because the recipient cannot be specified when the private method is invoked.

Predefined top-level methods

Puts,print are Kernel's built-in private instance methods that look at all the private methods that are available on Kernel:

Ruby-e ' P Kernel.private_instance_methods.sort '

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.