ruby 新建对象_Ruby面向对象编程简介

ruby 新建对象

by Nishant Mishra

由Nishant Mishra

Ruby面向对象编程简介 (An Introduction to Object-Oriented Programming with Ruby)

As a computer science student, I spend a lot of time learning and playing with new languages. Every new language has something unique to offer. Having said that, most beginners start off their programming journey with either procedural languages like C or with object-oriented languages like JavaScript and C++.

作为计算机科学专业的学生,​​我花了大量时间学习和使用新语言。 每种新语言都有其独特之处。 话虽如此,大多数初学者都是从程序语言(如C)或面向对象的语言(如JavaScript和C ++)开始编程的。

Therefore, it makes sense to go through the basics of object-oriented programming so you can understand the concepts and apply them to the languages you learn easily. We’ll be using the Ruby programming language as an example.

因此,通读面向对象编程的基础知识是有意义的,这样您就可以理解这些概念并将其应用于容易学习的语言。 我们将以Ruby编程语言为例。

You may be asking, why Ruby? Because it is “designed to make programmers happy” and also because almost everything in Ruby is an object.

您可能会问,为什么要使用Ruby? 因为它“旨在使程序员感到高兴”,而且因为Ruby中的几乎所有东西都是对象。

了解面向对象范例(OOP) (Getting a sense of the Object-Oriented Paradigm (OOP))

In OOP, we identify the “things” that our program handles. As humans, we think about things as objects with attributes and behaviors, and we interact with things based on these attributes and behaviors. A thing can be a car, a book, and so on. Such things become classes (the blueprints of objects), and we create objects out of these classes.

在OOP中,我们确定程序处理的“事物”。 作为人类,我们将事物视为具有属性和行为的对象,并基于这些属性和行为与事物进行交互。 事物可以是汽车,书籍等。 这样的东西变成了类(对象的蓝图),我们从这些类中创建了对象。

Each instance (object) contains instance variables which are the state of the object (attributes). Object behaviors are represented by methods.

每个实例(对象)包含实例变量,这些变量是对象(属性)的状态。 对象行为由方法表示。

Let’s take the example of a car. A car is a thing which would make it a class. A specific type of car, say BMW is an object of the class Car. The attributes/properties of a BMW such as the color and model number can be stored in instance variables. And if you want to perform an operation of the object, such as driving, then “drive” describes a behavior which is defined as a method.

让我们以汽车为例。 汽车是一种使它成为阶级的东西。 宝马(BMW)是一种特殊类型的汽车,是Car类的对象 BMW的属性/属性 (例如颜色和型号)可以存储在实例变量中。 并且,如果要执行对象的操作(例如驱动),则“驱动”描述了一种定义为方法的行为。

快速语法课 (A Quick Syntax Lesson)

  • To end a line in a Ruby program, a semicolon(;) is optional (but is generally not used)

    要在Ruby程序中结束一行,分号(;)是可选的(但通常不使用)
  • 2-space indentation for each nested level is encouraged (not required, like it is in Python)

    鼓励为每个嵌套级别使用2个空格的缩进(不是必需的,就像在Python中一样)
  • No curly braces {} are used, and the end keyword is used to mark the end of a flow control block

    不使用花括号{} ,并且使用end关键字标记流控制块的结尾

  • To comment, we use the # symbol

    要发表评论,我们使用#符号

The way objects are created in Ruby is by calling a new method on a class, as in the example below:

在Ruby中创建对象的方式是通过在类上调用方法,如以下示例所示:

class Car  def initialize(name, color)    @name = name    @color = color  end
def get_info    "Name: #{@name}, and Color: #{@color}"  endend
my_car = Car.new("Fiat", "Red")puts my_car.get_info

To understand what’s going on in the code above:

要了解上面的代码中发生了什么:

  • We have a class named Car with two methods, initialize and get_info.

    我们有一个名为Car的类,具有两个方法, initializeget_info

  • Instance variables in Ruby begin with @ (For example @name). The interesting part is that the variables are not initially declared. They spring into existence when first used, and after that they are available to all instance methods of the class.

    Ruby中的实例变量以@开头(例如@name )。 有趣的是,变量最初并未声明。 它们在首次使用时就存在,然后可用于该类的所有实例方法。

  • Calling the new method causes the initialize method to invoke. initialize is a special method which is used as a constructor.

    调用new方法将导致initialize方法被调用。 initialize是一种特殊的方法,用作构造函数。

存取资料 (Accessing Data)

Instance variables are private and can’t be accessed from outside the class. In order to access them, we need to create methods. Instance methods have public access by default. We can limit the access to these instance methods as we will see later in this article.

实例变量是私有的,不能从类外部访问。 为了访问它们,我们需要创建方法。 实例方法默认情况下具有公共访问权限。 我们可以限制对这些实例方法的访问,我们将在本文后面看到。

In order to get and modify the data, we need “getter” and “setter” methods, respectively. Let’s look at these methods taking the same example of a car.

为了获取和修改数据,我们分别需要“ getter”和“ setter”方法。 让我们以汽车为例来看看这些方法。

class Car  def initialize(name, color) # "Constructor"    @name = name    @color = color  end
def color    @color  end
def color= (new_color)    @color = new_color  endend
my_car = Car.new("Fiat", "Red")puts my_car.color # Red
my_car.color = "White"puts my_car.color # White

In Ruby, the “getter” and the “setter” are defined with the same name as the instance variable that we are dealing with.

在Ruby中,“ getter”和“ setter”的定义与我们要处理的实例变量的名称相同。

In the example above, when we say my_car.color, it actually calls the color method which in turn returns the name of the color.

在上面的示例中,当我们说my_car.color ,它实际上调用了color方法,该方法又返回颜色的名称。

Note: Pay attention to how Ruby allows a space between the color and equals to sign while using the setter, even though the method name is color=

注意: 使用方法时,即使方法名称为 color= ,也要 注意Ruby如何在 color equals 之间留出一个空格 以进行符号签名

Writing these getter/setter methods allow us to have more control. But most of the time, getting the existing value and setting a new value is simple. So, there should be an easier way instead of actually defining getter/setter methods.

编写这些getter / setter方法可以使我们拥有更多的控制权。 但是在大多数情况下,获取现有值并设置新值很简单。 因此,应该有一种比实际定义getter / setter方法更简单的方法。

更简单的方法 (The easier way)

By using the attr_* form instead, we can get the existing value and set a new value.

通过使用attr_*形式,我们可以获取现有值并设置一个新值。

  • attr_accessor: for getter and setter both

    attr_accessor :用于getter和setter两者

  • attr_reader: for getter only

    attr_reader :仅用于getter

  • attr_writer: for setter only

    attr_writer :仅适用于二传手

Let’s look at this form taking the same example of a car.

让我们以汽车的相同示例来看一下这种形式。

class Car  attr_accessor :name, :colorend
car1 = Car.newputs car1.name # => nil
car1.name = "Suzuki"car1.color = "Gray"puts car1.color # => Gray
car1.name = "Fiat"puts car1.name # => Fiat

This way we can skip the getter/setter definitions altogether.

这样,我们可以完全跳过getter / setter定义。

谈论最佳做法 (Talking about best practices)

In the example above, we didn’t initialize the values for the @name and @color instance variables, which is not a good practice. Also, as the instance variables are set to nil, the object car1 doesn’t make any sense. It’s always a good practice to set instance variables using a constructor as in the example below.

在上面的示例中,我们没有初始化@name@color实例变量的值,这不是一个好习惯。 另外,由于实例变量设置为nil,所以对象car1没有任何意义。 最好使用构造函数设置实例变量,如下例所示。

class Car  attr_accessor :name, :color    def initialize(name, color)    @name = name    @color = color  endend
car1 = Car.new("Suzuki", "Gray")puts car1.color # => Gray
car1.name = "Fiat"puts car1.name # => Fiat

类方法和类变量 (Class Methods and Class Variables)

So class methods are invoked on a class, not on an instance of a class. These are similar to static methods in Java.

因此,类方法是在类上而不是在类的实例上调用的。 这些类似于Java中的静态方法。

Note: self outside of the method definition refers to the class object. Class variables begin with @@

注意:方法定义之外的self引用类对象。 类变量以@@开头

Now, there are actually three ways to define class methods in Ruby:

现在,实际上有三种方法可以在Ruby中定义类方法:

在类定义内 (Inside the class definition)
  1. Using the keyword self with the name of the method:

    将关键字self与方法名称一起使用:
class MathFunctions  def self.two_times(num)    num * 2  endend
# No instance createdputs MathFunctions.two_times(10) # => 20

2. Using <<; self

2.使用<< ; 自

class MathFunctions  class << self    def two_times(num)      num * 2    end  endend
# No instance createdputs MathFunctions.two_times(10) # =&gt; 20
课外定义 (Outside the class definition)

3. Using class name with the method name

3.使用类名和方法名

class MathFunctionsend
def MathFunctions.two_times(num)  num * 2end
# No instance createdputs MathFunctions.two_times(10) # =&gt; 20

类继承 (Class Inheritance)

In Ruby, every class implicitly inherits from the Object class. Let’s look at an example.

在Ruby中,每个类都隐式继承自Object类。 让我们来看一个例子。

class Car  def to_s    "Car"  end
def speed    "Top speed 100"  endend
class SuperCar < Car  def speed # Override    "Top speed 200"  endend
car = Car.newfast_car = SuperCar.new
puts "#{car}1 #{car.speed}" # =&gt; Car1 Top speed 100puts "#{fast_car}2 #{fast_car.speed}" # => Car2 Top speed 200

In the above example, the SuperCar class overrides the speed method which is inherited from the Car class. The symbol &lt; denotes inheritance.

在上面的示例中, SuperCar类覆盖了从Car类继承的speed方法。 符号& lt; 表示继承。

Note: Ruby doesn’t support multiple inheritance, and so mix-ins are used instead. We will discuss them later in this article.

注意:Ruby不支持多重继承,因此使用混入。 我们将在本文后面讨论它们。

Ruby中的模块 (Modules in Ruby)

A Ruby module is an important part of the Ruby programming language. It’s a major object-oriented feature of the language and supports multiple inheritance indirectly.

Ruby模块是Ruby编程语言的重要组成部分。 它是该语言的主要面向对象功能,并间接支持多重继承。

A module is a container for classes, methods, constants, or even other modules. Like a class, a module cannot be instantiated, but serves two main purposes:

模块是类,方法,常量甚至其他模块的容器。 像类一样,模块无法实例化,但是有两个主要目的:

  • Namespace

    命名空间
  • Mix-in

    混入
模块作为命名空间 (Modules as Namespace)

A lot of languages like Java have the idea of the package structure, just to avoid collision between two classes. Let’s look into an example to understand how it works.

许多语言(例如Java)都具有包结构的思想,只是为了避免两个类之间的冲突。 让我们看一个例子来了解它是如何工作的。

module Patterns  class Match    attr_accessor :matched  endend
module Sports  class Match    attr_accessor :score  endend
match1 = Patterns::Match.newmatch1.matched = "true"
match2 = Sports::Match.newmatch2.score = 210

In the example above, as we have two classes named Match, we can differentiate between them and prevent collision by simply encapsulating them into different modules.

在上面的示例中,由于我们有两个名为Match类,我们可以通过将它们封装到不同的模块中来区分它们并防止冲突。

模块作为混入 (Modules as Mix-in)

In the object-oriented paradigm, we have the concept of Interfaces. Mix-in provides a way to share code between multiple classes. Not only that, we can also include the built-in modules like Enumerable and make our task much easier. Let’s see an example.

在面向对象的范例中,我们有接口的概念。 混合提供了一种在多个类之间共享代码的方法。 不仅如此,我们还可以包括诸如Enumerable类的内置模块,使我们的工作更加轻松。 让我们来看一个例子。

module PrintName  attr_accessor :name  def print_it    puts "Name: #{@name}"  endend
class Person  include PrintNameend
class Organization  include PrintNameend
person = Person.newperson.name = "Nishant"puts person.print_it # =&gt; Name: Nishant
organization = Organization.neworganization.name = "freeCodeCamp"puts organization.print_it # =&gt; Name: freeCodeCamp

Mix-ins are extremely powerful, as we only write the code once and can then include them anywhere as required.

混合功能非常强大,因为我们只编写一次代码,然后可以根据需要在任何地方包含它们。

Ruby中的范围 (Scope in Ruby)

We will see how scope works for:

我们将看到范围如何工作:

  • variables

    变数
  • constants

    常数
  • blocks

变量范围 (Scope of variables)

Methods and classes define a new scope for variables, and outer scope variables are not carried over to the inner scope. Let’s see what this means.

方法和类为变量定义了新的作用域,并且外部作用域变量不会继承到内部作用域。 让我们看看这意味着什么。

name = "Nishant"
class MyClass  def my_fun    name = "John"    puts name # =&gt; John  end
puts name # =&gt; Nishant

The outer name variable and the inner name variable are not the same. The outer name variable doesn’t get carried over to the inner scope. That means if you try to print it in the inner scope without again defining it, an exception would be thrown — no such variable exists

外部name变量和内部name变量不同。 外部name变量不会继承到内部范围。 这意味着,如果您尝试在内部范围中打印它而不再次定义它,则将引发异常- 不存在此类变量

常数范围 (Scope of constants)

An inner scope can see constants defined in the outer scope and can also override the outer constants. But it’s important to remember that even after overriding the constant value in the inner scope, the value in the outer scope remains unchanged. Let’s see it in action.

内部作用域可以看到在外部作用域中定义的常量,也可以覆盖外部常量。 但重要的是要记住,即使在覆盖内部作用域中的常量值之后,外部作用域中的值仍保持不变。 让我们来看看它的作用。

module MyModule  PI = 3.14  class MyClass    def value_of_pi      puts PI # =&gt; 3.14      PI = "3.144444"      puts PI # => 3.144444    end  end  puts PI # =&gt; 3.14end
块的范围 (Scope of blocks)

Blocks inherit the outer scope. Let’s understand it using a fantastic example I found on the internet.

块继承外部范围。 让我们用我在互联网上找到的一个很棒的例子来理解它。

class BankAccount  attr_accessor :id, :amount  def initialize(id, amount)    @id = id    @amount = amount  endend
acct1 = BankAccount.new(213, 300)acct2 = BankAccount.new(22, 100)acct3 = BankAccount.new(222, 500)
accts = [acct1, acct2, acct3]
total_sum = 0accts.each do |eachAcct|  total_sum = total_sum + eachAcct.amountend
puts total_sum # =&gt; 900

In the above example, if we use a method to calculate the total_sum, the total_sum variable would be a totally different variable inside the method. That’s why sometimes using blocks can save us a lot of time.

在上面的示例中,如果我们使用一种方法来计算total_sum ,则total_sum变量将是该方法内部的完全不同的变量。 这就是为什么有时使用块可以节省大量时间的原因。

Having said that, a variable created inside the block is only available to the block.

话虽如此,在块内部创建的变量仅对块可用。

访问控制 (Access Control)

When designing a class, it is important to think about how much of it you’ll be exposing to the world. This is known as Encapsulation, and typically means hiding the internal representation of the object.

设计课程时,重要的是要考虑要向世界展示多少课程。 这就是所谓的封装,通常意味着隐藏对象的内部表示。

There are three levels of access control in Ruby:

Ruby中的访问控制分为三个级别:

  • Public - no access control is enforced. Anybody can call these methods.

    公开 -不执行访问控制。 任何人都可以调用这些方法。

  • Protected - can be invoked by objects of the defining classes or its sub classes.

    受保护的 -可以由定义类或其子类的对象调用。

  • Private - cannot be invoked except with an explicit receiver.

    专用 -除非使用显式接收者,否则不能调用。

Let’s see an example of Encapsulation in action:

让我们看一个封装实际的例子:

class Car  def initialize(speed, fuel_eco)    @rating = speed * comfort  end
def rating    @rating  endend
puts Car.new(100, 5).rating # =&gt; 500

Now, as the details of how the rating is calculated are kept inside the class, we can change it at any point in time without any other change. Also, we cannot set the rating from outside.

现在,由于如何计算评分的详细信息保留在班级内部,因此我们可以随时更改它,而无需进行其他任何更改。 另外,我们不能从外部设置等级。

Talking about the ways to specify access control, there are two of them:

谈到指定访问控制的方法,有两种:

  1. Specifying public, protected, or private and everything until the next access control keyword will have that access control level.

    指定public,protected或private以及所有内容,直到下一个访问控制关键字将具有该访问控制级别。
  2. Define the method regularly, and then specify public, private, and protected access levels and list the comma(,) separated methods under those levels using method symbols.

    定期定义方法,然后指定公共,私有和受保护的访问级别,并使用方法符号在这些级别下列出逗号分隔的方法。
第一种方式的示例: (Example of the first way:)
class MyClass  private    def func1      "private"    end  protected    def func2      "protected"    end  public    def func3      "Public"    endend
第二种方式的示例: (Example of the second way:)
class MyClass  def func1    "private"  end  def func2    "protected"  end  def func3    "Public"  end  private :func1  protected :func2  public :func3end

Note: The public and private access controls are used the most.

注意:最常使用公共和私人访问控制。

结论 (Conclusion)

These are the very basics of Object Oriented Programming in Ruby. Now, knowing these concepts you can go deeper and learn them by building cool stuff.

这些是Ruby中面向对象编程的基础知识。 现在,了解了这些概念后,您可以通过构建有趣的东西来更深入地学习它们。

Don’t forget to clap and follow if you enjoyed! Keep up with me here.

如果您喜欢的话,别忘了拍手并跟随! 在这里跟上我。

翻译自: https://www.freecodecamp.org/news/an-introduction-to-object-oriented-programming-with-ruby-73531e2b8ddc/

ruby 新建对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值