Programming ruby-class, object, inheritance and message

Source: Internet
Author: User

From the example we demonstrated above, you may be surprised that the ruby we declared earlier is an object-oriented language.
So we can prove it through this chapter. We will introduce how to use Ruby to create classes and objects, and introduce what Ruby is more powerful than most object-oriented languages.
Let's implement one million dollar product step by step, part of the Internet enabled jazz and bluegrass automatic changers.
After months of work, our high-income researchers and developers confirmed that our automatic changers needed songs. Therefore, creating a ruby class to describe a song is a good idea.
We know that a real song has names, singers, and time, because we need to ensure that Program The same is true for the target of zhongge.
Let's start to create a new base class song, which contains only one method initialize.
Class song
Def initialize (name, artist, duration)
@ Name = Name
@ Artist = artist
@ Duration = duration
End
End
Initialize is a special method in Ruby programs. When you call song. New to create a new song object, Ruby allocates some memory to store an object that has not been initialized,
Call the initialize method of the object and pass in all parameters passed to new. This method is used to create the object state.
In the song class, the initialize method has three parameters. These parameters are like local variables in the method. Therefore, they follow the naming conventions of local variables and start with a lowercase letter.
Each object corresponds to its own song, so we need these song objects to save their own song names, singers and time. That is, these values are saved as instance variables in the object.
Instance variables can be accessed by all methods in the object, and each object has its own copy of instance variables.
In Ruby, the instance variable is simply added with the "at" symbol (@) before the name (@). In our example, the parameter name is assigned to the instance variable @ name and artist to @ artist,
Duration (the length of the song, in seconds) is assigned to @ duration.
Let's test our beautiful new class.
Song = song. New ("bicylops", "fleck", 260)
Song. Inspect-> # <Song: 0x1c7ca8 @ name = "bicylops", @ duration = 260, @ artist = "fleck">
Yes, it seems to work. By default, inspect information can be passed into any object to format the Object ID and instance variables. We can see that we have created them correctly.
Experience tells us that during development, we will print the song content multiple times, and the default inspect format has some information we want. Fortunately, Ruby has a standard message, to_s,
It is passed to any object to be displayed as a string. Let's try it out on our song.
Song = song. New ("bicylops", "fleck", 260)
Song. to_s-> "# <Song: 0x1c7ec4>"
This is not very practical-it only returns the Object ID. Therefore, let's rewrite it in the class. Before that, let's discuss how we define a class in this book.
In Ruby, classes are never closed: You can add methods to an existing class at any time. It applies to the classes you write and standard built-in classes.
For the definition of an existing open class, the new content you specify will be added to any class.
This is our important purpose. Before going into this chapter, we will add some features to our class. We will only demonstrate the new methods defined by this class. The original class still exists.
This eliminates the need to repeat redundant content in each example. Obviously, if the newly created Code You may write all the methods in a separate class definition.
I have learned enough about it. Let's add a to_s method to our song class. We will use the # character in the string to insert the values of these three instance variables.
Class song
Def to_s
"Song: # @ name -- # @ artist (# @ duration )"
End
End
Song = song. New ("bicylops", "fleck", 260)
Song. to_s-> "Song: bicylops -- Fleck (260 )"
Good. improvements have been made. However, we mix some more subtle things together. We said that all Ruby objects support to_s, but we didn't say how to support it.
This answer involves inheritance, subclass, and how Ruby determines which method to run when an object receives a message. This topic is left to a new chapter, so...

Inheritance and information
Inheritance allows you to create such a class, which is the specific implementation or special implementation of another class.
For example, our automatic phonograph has the concept of song, And we encapsulate it in the Song class. Market demand tells us that we need to provide support for karaoke.
Karaoke songs are very similar to other songs (without audio tracks, which I have seen is irrelevant to us. It also carries the lyrics and time information. When playing karaoke on our automatic phonograph,
The lyrics must be synchronized with the music on the player's screen.
One method to solve the problem is to define a new class karaokesong, which is the same as song and only has a new line of lyrics.
Class karaokesong <song
Def initialize (name, artist, duration, lyrics)
Super (name, artist, duration)
@ Lyrics = lyrics
End
End
The "<song" on the class definition line tells Ruby that karaokesong is a subclass of song. (No surprise, that is to say, Song is karaokesong and is a superclass.
People also use the parent-child relationship to describe, so karaokesong's father is song .) Now, you don't have to worry about its inheritance method. We will explain the super call later.
Let's create a karaokesong to see if it can run. (In the final system, the lyrics are stored in an object containing text and time information .)
A string to test our class. This is another benefit of dynamic languages-we don't need to define anything before code runs.
Song = karaokesong. New ("My Way", "Sinatra", 225, "and now, ...")
Song. to_s! "Song: My waysinatra (225 )"
Yes, it is running. But why didn't the lyrics be displayed in the to_s method?
This question needs to be answered when you pass information to the object, Ruby decides which method should be called.
In the program code that was originally passed, when Ruby finds the song. to_s method call, it does not actually know where to find the to_s method.
Instead, it delays this decision until the program runs. At this time, it looks for the song class. If this class implements the same name as the method passed to it as information,
Run this method. Otherwise, Ruby will search for this method in its parent class, and then the parent class, always going up. If you still cannot find the appropriate method,
It executes a special action and throws an error.
Return to our example. We pass the to_s information to song, which is an object of the karaokesong class. Ruby finds the to_s method in karaokesong but does not find it.
This compiler then looks for karaokesong's parent class, Song class, where it finds the to_s method we have defined. This is why it prints the song details
There is no reason for the lyrics, because song does not know lyrics.
Let's implement the to_s method of karaokesong to correct it. You can implement multiple methods. Let's start in a bad way. Copy to_s from Song and add lyric.
Class karaokesong
#...
Def to_s
"KS: # @ name #@
Artist (# @ duration) [# @ lyrics]"
End
End
Song = karaokesong. New ("My Way", "Sinatra", 225, "and now, ...")
Song. to_s-> "KS: My waysinatra (225) [and now, the...]"
The value of the instance variable @ lyrics is correctly displayed. In this method, the subclass directly accesses the instance variables of the parent class.
So why is it a bad way to implement to_s.
This answer is related to a good programming method (decoupling ). By viewing the internal structure of the parent class and explicitly using its instance variables, code is coupled.
If we decide to modify the unit of time for the song to save the song, the unit is milliseconds. Suddenly, karaokesong will display a ridiculous value.
For the problem that each class has its own implementation details, when karaokesong # to_s is called, we will first call the to_s method of its parent class to obtain the detailed information of the song.
Then, append the lyrics to it and return the results.
The ruby keyword super is used here. When you do not pass the parameter to call Super, Ruby sends a message to the parent class of the current object, asking it to call the method with the same name as the parent class.
The method parameter passed in is the parameter passed in by the method previously called. Now we can implement to_s with new improvements.
Class karaokesong <song
# Format ourselves as a string by appending
# Our lyrics to our parent's # to_s value.
Def to_s
Super + "[# @ lyrics]"
End
End
Song = karaokesong. New ("My Way", "Sinatra", 225, "and now, ...")
Song. to_s-> "Song: My waysinatra (225) [and now, the...]"
We explicitly tell Ruby karaokesong that the parent class is song, but we do not explicitly specify the parent class of song.
If you do not specify the parent class when defining a class, Ruby provides the object class by default. That is to say, all objects in Ruby have an ancestor object, and all instance methods of the object are available for each object.

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.