Ruby Object-Oriented
Ruby is a pure object-oriented language, and everything in Ruby takes the form of objects. Every value in Ruby is an object, even the most primitive things: strings, numbers, and even true and false are objects. The class itself is also anobject, which isClassan instance of the Class class. This chapter will explain all the main features related to Ruby object-oriented programming.
Classes are used to specify the form of objects. They combine data representation and methods, organizing data into a neat package. The data and methods in a class are called members of the class.
Ruby Class Definition
When you define a class, you are actually defining a blueprint for a data type. This does not actually define any data, but rather defines what the class name means, that is, what the objects of the class will consist of and what operations can be performed on the object.
A class definition starts with the keywordclassand is followed bythe class name, and finally ends withenda separator to mark the end of the class definition. For example, we use the keyword class to define the Box class, as shown below:
By convention, the name must begin with a capital letter. If it contains multiple words, capitalize the first letter of each word, but with no separators between them (e.g., CamelCase).
Defining Ruby Objects
Classes provide the blueprint for objects, so basically, objects are created based on the class. We use thenewkeyword to declare objects of the class. The following statement declares two objects of class Box:
The initialize Method
initializeThe method is a standard Ruby class method, serving as the class constructor, and is similar to theconstructorworking principle in other object-oriented programming languages. When you want to initialize some class variables while creating an object, the initialize method comes in handy. This method takes a series of parameters; like other Ruby methods, when using it, you must place thedefkeyword before it, as shown below:
Instance Variables
Instance variablesare class attributes. When objects are created using the class, they become the attributes of the objects. Each object's attributes are assigned separately and do not share values with other objects. Inside the class, these attributes are accessed using the @ operator; outside the class, they are accessed using methods calledaccessor methods, which areofpublicmethods. Below we take the class defined aboveBoxas an example, and use @width and @height as the instance variables of class Box.
Accessor (getter) & Setter (setter) Methods
To read variables defined in a class from outside the class, we can define accessor (getter) methods to access them. The following example demonstrates the usage of accessor methods:
Example
Try it »
When the above code is executed, it produces the following result:
盒子宽度 : 10 盒子高度 : 20
Similar to accessor methods used to access variable values, Ruby provides a way to pass parameters to variables defined in a class from outside the class, the so-calledsetter methods, defined as follows:
Example
Try it »
When the above code is executed, it produces the following result:
盒子宽度 : 30 盒子高度 : 50
Since both methods are very commonly used, Ruby definesattr_accessor :variable_name、attr_reader :variable_name、attr_writer :variable_namethree attribute declaration methods. Among them:accessor=reader+writer。
Also note: the variable name must be prefixed with:, and between variable names use,to separate.
Instance Methods
Instance methodsare defined in the same way as other methods, using thedefkeyword, but they can only be used through class instances, as shown in the example below. Their functions are not limited to accessing instance variables; they can also perform many other tasks as needed.
Example
Try it »
When the above code is executed, it produces the following result:
Area of the box is : 200
Class Methods & Class Variables
Class variablesare variables shared by all instances of a class. In other words, class variables can be accessed by all object instances. Class variables are prefixed with two @ characters (@@). Class variables must be initialized in the class definition, as shown in the example below.
Class methodsare defined using thedef self.methodname()keyword, and class methods end with the end delimiter. Class methods can be called using theclassname.methodnameform with the class name, as shown in the example below:
Example
Try it »
When the above code is executed, it produces the following result:
Box count is : 2
The to_s Method
Any class you define has anto_sinstance method to return the string representation of the object. The following is a simple example representing Box objects based on width and height:
Example
Try it »
When the above code is executed, it produces the following result:
String representation of box is : (w:10,h:20)
Access Control
Ruby provides you with three levels of instance method protection, namelypublic, private, or protected. Ruby does not apply any access control to instance and class variables.
- Public methods:Public methods can be called by any object. By default, methods are public, except the initialize method, which is always private.
- Private methods:Private methods cannot be accessed or viewed from outside the class. Only class methods can access private members.
- Protected methods:Protected methods can only be called by objects of the class and its subclasses. Access can also be performed only inside the class and its subclasses.
The following is a simple example demonstrating the syntax of these three modifiers:
Example
Try it »
When the above code is executed, it produces the following result. Here, the first method call succeeds, but the second method causes a problem.
Area of the box is : 200 test.rb:42: protected method `printArea' called for # <Box:0xb7f11280 @height=20, @width=10> (NoMethodError)
Class Inheritance
Inheritance is one of the most important concepts in object-oriented programming. Inheritance allows us to define a class based on another class, making it easier to create and maintain applications.
Inheritance helps with code reuse and fast execution. Unfortunately, Ruby does not support multiple inheritance, but Ruby supportsmixinsmixins. Mixins are like a specific implementation of multiple inheritance, where only the interface part is inheritable.
When creating a class, the programmer can directly specify that the new class inherits the members of an existing class, thus avoiding writing new data members and member functions from scratch. This existing class is calledbase class or parent class, and the new class is calledderived class or subclass。
Ruby also provides the concept of subclassing, which is inheritance. The following example explains this concept. The syntax for extending a class is very simple. Just add a < character and the name of the parent class to the class statement. For example, the following defines the class'sBigBoxYesBoxsubclass:
Example
Try it »
When the above code is executed, it produces the following result:
Big box area is : 200
Method Overloading
Although you can add new functionality in a derived class, sometimes you may want to change the behavior of a method already defined in the parent class. In this case, you can keep the method name unchanged and override the method's functionality, as shown in the following example:
Example
Try it »
The output of the above example is:
Big box area is : 200
Operator Overloading
We want to use the + operator to perform vector addition of two Box objects, use the * operator to multiply the width and height of Box, and use the unary operator - to negate the width and height of Box. Below is a version of the Box class with mathematical operator definitions:
Freezing Objects
Sometimes, we want to prevent objects from being changed. In Object, the freeze method can achieve this, effectively turning an object into a constant. Any object can be frozen by callingObject.freezefreeze. A frozen object cannot be modified, that is, you cannot change its instance variables.
You can use theObject.frozen?method to check whether a given object has been frozen. If the object is frozen, this method returns true; otherwise, it returns a false value. The following example explains this concept:
Example
Try it »
When the above code is executed, it produces the following result:
Box object is frozen object
test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
from test.rb:39
Class Constants
You can define a constant inside a class by assigning a direct numeric or string value to a variable. Constants do not need to use @ or @@. By convention, constant names are capitalized.
Once a constant is defined, you cannot change its value. You can access the constant directly inside the class, just like accessing a variable, but if you want to access the constant outside the class, you must useclassname::constant::, as shown in the following example.
Example
Try it »
When the above code is executed, it produces the following result:
Area of the box is : 200 TATA Inc Box weight is: 10
Class constants can be inherited, and can also be overridden like instance methods.
Creating Objects Using allocate
There may be a situation where you want to create an object without calling the object constructorinitialize, i.e., without using the new method to create an object. In this case, you can call allocate to create an uninitialized object, as shown in the following example:
Example
Try it »
When the above code is executed, it produces the following result:
Area of the box is : 200 test.rb:14: warning: instance variable @width not initialized test.rb:14: warning: instance variable @height not initialized test.rb:14:in `getArea': undefined method `*' for nil:NilClass (NoMethodError) from test.rb:29
Class Information
Ruby's self and Java's this have similarities, but are also quite different. In Java, methods are referenced within instance methods, so this generally points to the current object. Ruby's code executes line by line, so self has different meanings in different contexts. Let's look at the following example:
Example
Try it »
When the above code is executed, it produces the following result:
Class of self = Class Name of self = Box
This means that the class definition can be executed by treating the class as the current object, and it also means that the methods in the metaclass and parent class are available during the execution of the method definition.
Other Extensions