English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Ruby is a pure object-oriented language, where everything in Ruby appears in the form of an object. 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, is Class A class example. This chapter will explain all the main features related to Ruby object-oriented programming.
A class is used to specify the form of an object, combining data representation and methods to organize data into a neat package. The data and methods in the class are called members of the class.
When you define a class, you are actually defining a blueprint for a data type. This does not define any data at all, but defines what the class name means, that is, defines what the objects of the class will consist of and what operations can be performed on the object.
Class definitions are terminated with the keyword class followed byclass name, and finally, start with a end to separate and indicate the end of the class definition. For example, we use the keyword class to define the Box class, as follows:
class Box code end
By convention, the name must start with an uppercase letter, and if it contains multiple words, each word must start with an uppercase letter without any separators (e.g., CamelCase).
The class provides the blueprint for objects, so in essence, objects are created based on the class. We use new Keywords are used to declare class objects. The following statements declare two objects of the class Box:
box1 = Box.new box2 = Box.new
initialize Method is a standard Ruby class method, which is the constructor of the class, similar to the initialize method in other object-oriented programming languages. constructor The work principle is similar. When you want to initialize some class variables at the same time as creating an object, the initialize method comes into play. This method takes a series of parameters, like other Ruby methods, and when using this method, it must be prefixed with def Keywords, as shown below:
class Box def initialize(w,h) @width, @height = w, h end end
Example variableInstance attributes, which become object properties when objects are created from the class. Each object's properties are assigned separately and do not share values with other objects. Inside the class, these properties are accessed using the @ operator, and outside the class, they are accessed using what is calledaccessor methodofPublicmethod to access. Below we use the class Box For example, take @width and @height as instance variables of the class Box.
class Box def initialize(w,h) # Assign value to example variable @width, @height = w, h end end
To read class-defined variables from outside the class, we can define accessor (getter) methods to access. The following example demonstrates the usage of accessor methods:
#!/usr/bin/ruby -w # Define class class Box # Constructor def initialize(w,h) @width, @height = w, h end # Accessor methods def printWidth @width end def printHeight @height end end # Create object, initialize the height and width of the box box = Box.new(10, 20) # Use accessor methods x = box.printWidth() y = box.printHeight() puts "Box width: #{x}" puts "Box height: #{y}"
When the above code is executed, it will produce the following result:
Box width : 10 Box height : 20
Similar to the accessor method used to access variable values, Ruby provides a way to pass parameters into class-defined variables from outside the class, which is known asSetter method, defined as follows:
#!/usr/bin/ruby -w # Define class class Box # Constructor method def initialize(w,h) @width, @height = w, h end # Accessor methods def getWidth @width end def getHeight @height end # Setter methods def setWidth=(value) @width = value end def setHeight=(value) @height = value end end # Creating an object box = Box.new(10, 20) # Use setter method box.setWidth = 30 box.setHeight = 50 # Use accessor methods x = box.getWidth() y = box.getHeight() puts "Box width: #{x}" puts "Box height: #{y}"
When the above code is executed, it will produce the following result:
Box width : 30 Box height : 50
Since both methods are very commonly used, Ruby defines attr_accessor :variable_name, attr_reader :variable_name, attr_writer :variable_name Three methods of attribute declaration. Among them:accessor = reader+writer.
At the same time, note that the variable name must be prefixed with : and separated by , between variable names.
instance methoddefinition is the same as other method definitions, both using def keywords, but they can only be used through class instances, as shown in the following example. Their functions are not limited to accessing instance variables, but can also perform other tasks as needed.
#!/usr/bin/ruby -w # Define class class Box # Constructor def initialize(w,h) @width, @height = w, h end # Example method def getArea @width * @height end end # Creating an object box = Box.new(10, 20) # Calling example method a = box.getArea() puts "Area of the box is: #{a}"
When the above code is executed, it will produce the following result:
Area of the box is: 200
Class variableare shared variables in all instances of the class. In other words, the class variable instances can be accessed by all object instances. Class variables are prefixed with two @ characters (@@), and class variables must be initialized within the class definition, as shown in the following example.
class methodsuse def self.methodname() Definition, class methods end with the delimiter end. Class methods can use classname.methodname Formal call, as shown in the following example:
#!/usr/bin/ruby -w class Box # Initialize class variable @@count = 0 def initialize(w,h) # Assign value to example variable @width, @height = w, h @@count += 1 end def self.printCount() puts "Box count is: #@@count" end end # Create two objects box1 = Box.new(10, 20) box2 = Box.new(30, 100) # Call a class method to output the box count Box.printCount()
When the above code is executed, it will produce the following result:
Box count is: 2
Every class you define has a to_s Example methods to return the string representation of an object. Below is a simple example representing the Box object based on width and height:
#!/usr/bin/ruby -w class Box # Constructor method def initialize(w,h) @width, @height = w, h end # Define the to_s method def to_s "(w:#@width,h:#@height)" # Object string format end end # Creating an object box = Box.new(10, 20) # Automatically call the to_s method puts "String representation of box is: #{box}"
When the above code is executed, it will produce the following result:
String representation of box is: (w:10,h:20)
Ruby provides three levels of method protection, namely public, private, or protected. Ruby does not apply any access control to examples and class variables.
Public methods: Public methods can be called by any object. By default, methods are public, except that the initialize method 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 is also restricted to the class and its subclasses.
Below is a simple example demonstrating the syntax of these three modifiers:
#!/usr/bin/ruby -w # Define class class Box # Constructor method def initialize(w,h) @width, @height = w, h end # Example methods are public by default def getArea getWidth() * getHeight end # Define private accessor methods def getWidth @width end def getHeight @height end # Make them private private :getWidth, :getHeight # Example method for outputting area def printArea @area = getWidth() * getHeight puts "Big box area is: #@area" end # Make the example method protected protected :printArea end # Creating an object box = Box.new(10, 20) # Calling example method a = box.getArea() puts "Area of the box is: #{a}" # Attempt to call a protected example method box.printArea()
When the above code is executed, it will produce the following results. In this case, the first method call is successful, but the second method will cause a problem.
Area of the box is: 200 test.rb:42: protected method `printArea' called for # <Box:0xb7f11280 @height=20, @width=10(NoMethodError)
inheritance, which 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 supports mixins.Mixin is 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 from the members of an existing class, so that new data members and member functions do not need to be written from scratch. This existing class is calledbase class or superclass, 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 to extend a class is very simple. Just add a < character and the name of the superclass to the class statement. For example, the following defines the class BigBox is Box The subclass of
#!/usr/bin/ruby -w # Define class class Box # Constructor method def initialize(w,h) @width, @height = w, h end # Example method def getArea @width * @height end end # Define subclass class BigBox < Box # Add a new example method def printArea @area = @width * @height puts "Big box area is: #@area" end end # Creating an object box = BigBox.new(10, 20) # Output the area box.printArea()
When the above code is executed, it will produce the following result:
Big box area is : 200
Although you can add new features in the derived class, sometimes you may want to change the behavior of methods already defined in the superclass. In this case, you can keep the method name unchanged and overload the functionality of the method, as shown in the following example:
#!/usr/bin/ruby -w # Define class class Box # Constructor method def initialize(w,h) @width, @height = w, h end # Example method def getArea @width * @height end end # Define subclass class BigBox < Box # Modify the existing getArea method def getArea @area = @width * @height puts "Big box area is: #@area" end end # Creating an object box = BigBox.new(10, 20) # Output the area using overloaded method box.getArea()
The following example is the output result of the run:
Big box area is : 200
We want to use + Operator to perform vector addition between two Box objects, using * Operator to multiply the width and height of Box, using unary operator - Reverse the width and height of Box. Here is a version of the Box class with defined mathematical operators:
class Box def initialize(w,h) # Initialize width and height @width, @height = w, h end def +(other) # Define + to perform vector addition Box.new(@width + other.width, @height + other.height) end def -# Define a unary operator - reverse the width and height Box.new(-@width, -@height) end def *(scalar) # Perform scalar multiplication Box.new(@width*scalar, @height*scalar) end end
Sometimes, we want to prevent an object from being changed. In Object, the freeze method can achieve this, effectively turning an object into a constant. Any object can be frozen by calling Object.freeze to freeze. A frozen object cannot be modified, which means you cannot change its instance variables.
You can use Object.frozen? The method checks whether a given object has been frozen. If the object has been frozen, the method returns true, otherwise it returns a false value. The following example explains this concept:
#!/usr/bin/ruby -w # Define class class Box # Constructor method def initialize(w,h) @width, @height = w, h end # Accessor methods def getWidth @width end def getHeight @height end # Setter methods def setWidth=(value) @width = value end def setHeight=(value) @height = value end end # Creating an object box = Box.new(10, 20) # Let's freeze the object box.freeze if(box.frozen?) puts "Box object is a frozen object" else puts "Box object is a normal object" end # Now try using setter methods box.setWidth = 30 box.setHeight = 50 # Use accessor methods x = box.getWidth() y = box.getHeight() puts "Width of the box is: #{x}" puts "Height of the box is: #{y}"
When the above code is executed, it will produce the following result:
Box object is a frozen object test.rb:20:in `setWidth=': can't modify frozen object (TypeError) from test.rb:39
You can define a constant within the class by assigning a direct numeric or string value to a variable. The definition of a constant does not require the use of @ or @@. By convention, the names of constants are written in uppercase.
Once a constant is defined, you cannot change its value. You can access the constant directly within the class, just like a variable, but if you want to access the constant outside the class, you must use classname::constantas shown in the following example.
#!/usr/bin/ruby -w # Define class class Box BOX_COMPANY = "TATA Inc" BOXWEIGHT = 10 # Constructor method def initialize(w,h) @width, @height = w, h end # Example method def getArea @width * @height end end # Creating an object box = Box.new(10, 20) # Calling example method a = box.getArea() puts "Area of the box is: #{a}" puts Box::BOX_COMPANY puts "Box weight is: #{Box::BOXWEIGHT}"
When the above code is executed, it will produce the following result:
Area of the box is: 200 TATA Inc Box weight is: 10
Class constants can be inherited and can also be overloaded like example methods.
There may be a situation where you want to create an object without calling the object constructor initialize In the case of creating an object, that is, 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:
#!/usr/bin/ruby -w # Define class class Box attr_accessor :width, :height # Constructor method def initialize(w,h) @width, @height = w, h end # Example method def getArea @width * @height end end # Using new to create an object box1 = Box.new(10, 20) # Using allocate to create another object box2 = Box.allocate # Using box1 Calling example method a = box1.getArea() puts "Area of the box is: #{a}" # Using box2 Calling example method a = box2.getArea() puts "Area of the box is: #{a}"
When the above code is executed, it will produce 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
Ruby's self and Java's this have similarities, but they are also quite different. Java methods always refer to the current object in the example method, so this usually points to the current object. However, Ruby code is executed line by line, so self has different meanings in different contexts. Let's take a look at the following example:.
#!/usr/bin/ruby -w class Box # Output class information puts "Class of self = #{self.class}" puts "Name of self = #{self.name}" end
When the above code is executed, it will produce 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, which also means that the method in the metaclass and superclass is available during the execution of the method definition.