第1部分简介

Object oriented programming (OOP) is a programming paradigm. It allows us to represent the complexities of the real, physical world in a digital way. Languages that support some level of object-orientation are ubiquitous — they include Ruby, Python, Javascript, PHP, C++, C #, Java, Rust, Kotlin, Go, and many others.

面向对象编程(OOP)是一种编程范例。 它使我们能够以数字方式表示现实世界的复杂性。 支持某种程度的面向对象的语言无处不在-它们包括Ruby,Python,Javascript,PHP,C ++,C#,Java,Rust,Kotlin,Go以及许多其他语言。

This is the first article in a two-part series that will approach the topic of OOP using Ruby to illustrate ideas and is intended for those who have an understanding of the fundamentals of procedural programming and are learning OOP.

这是一个由两部分组成的系列文章的第一篇,该系列文章将使用Ruby来探讨OOP主题,以说明思想,并且适合那些了解过程编程基础并且正在学习OOP的人。

At its core, OOP consists of classes and objects made from those classes.

OOP的核心是类和由这些类组成的对象。

类决定属性和行为 (Classes determine attributes and behaviors)

A class is a blueprint or a template for objects. It is the concept or idea of a thing, while an object is one physical manifestation of that concept. For example, take the concept of a book. Picture one in your mind. What do you see? In other words, what makes a book a book?

类是对象的蓝图或模板。 它是事物的概念观念 ,而对象是该概念的一种物理表现。 例如,以一本书的概念为例。 想一想。 你看到了什么? 换句话说,是什么使一本书成为一本书?

Image for post
Photo by ASTERISK on Unsplash
ASTERISKUnsplash拍摄的照片

A book has attributes

一本书具有属性

  • Some potentially captivating title

    一些潜在的迷人标题
  • Some author/s who wrote it

    一些作者写的
  • Some number of pages

    若干页
  • Some type of paperback or hardcover binding

    某种平装书或精装本
  • A cover that is some color

    有颜色的封面
  • Some measurable weight

    一些可衡量的体重

These are all characteristics — they describe the book. Instance variables are the attributes that an individual book has (e.g., a title of Harry Potter and the Chamber of Secrets, a page number of 432, a weight of 0.74 lbs). The total amalgamation of all instance variables an individual book has make up that particular book’s state.

这些都是特征-它们描述了本书。 实例变量是一本书所具有的属性(例如,《 哈利·波特与密室》的书名,页数为432,权重为0.74磅)。 一本书的所有实例变量的总合并构成了该书的状态。

Specific actions can be done with a book

一本书可以完成特定的动作

  • It can be read

    可以阅读
  • It can be picked up

    可以拿起
  • It can be put down

    可以放下
  • It can be thrown

    可以扔
  • Pages can be ripped out

    页面可以被撕掉
  • Notes can be written in the margins

    笔记可以写在空白处

In OOP, the actions that you can do with an object are defined in the class definition. They are called instance methods, and can be called on any object made from the class.

在OOP中,可以在类定义中定义可以对对象执行的操作。 它们被称为实例方法 ,并且可以在由类制成的任何对象上被调用。

Taking a step back, a class dictates the possible attributes or characteristics of objects that are made from it.

退后一步,类规定了由此类对象的可能属性或特性。

Let’s focus on three key attributes — the title, author, and number of pages to create a Book class below.

让我们关注三个关键属性-标题,作者和在下面创建Book类的页面数。

class Book
def initialize(title, author, pages)
@title = title
@author = author
@pages = pages
end
end

Within our simple Book class definition is a special instance method initialize. This is Ruby’s constructor method. It is triggered every time the class method ::new is called on the Book class. Note that initialize is a private instance method, which means it cannot be called outside of a class definition. Additionally, if the initialize method is defined to take parameters, the ::new method must be passed arguments (unless the parameters defined within the class definition are given default parameters).

在我们简单的Book类定义中,有一个特殊的实例方法initialize 。 这是Ruby的构造方法。 每次在Book类上调用类方法::new时,都会触发该事件。 请注意, initialize是一个私有实例方法,这意味着不能在类定义之外调用它。 此外,如果将initialize方法定义为采用参数,则必须将::new方法传递给参数(除非在类定义中定义的参数被赋予了默认参数)。

实例变量组成状态 (Instance variables compose state)

You may have noticed the variables prefixed with @ . Instance variables are denoted with the @ sign (also known as the sigil). These variables are scoped at the object level — they are available to all instance methods defined within a class, and each object made from a class has its own copy of the variable that can hold its own value.

您可能已经注意到以@开头的变量。 实例变量用@符号表示(也称为符号)。 这些变量在对象级别作用域-它们可用于类中定义的所有实例方法,并且由类构成的每个对象都有其自己的变量副本,这些副本可以保存自己的值。

With our class defined, we can call new directly on the class, feeding it the information we want to use to create the initial state of the object.

定义好我们的类后,我们可以直接在类上调用new ,向它提供我们想要用来创建对象初始状态的信息。

Book.new('Triumph of the City', 'David Glaeser', 338)
Image for post
Photo by Almos Bechtold on Unsplash
Almos BechtoldUnsplash拍摄的照片

We have created, or instantiated one Book object — one instance of the Book class. This book has a bundle of instance variables — @title, @author, and @pages. The instance variables of this particular instance of the class are bound to the values we pass to the ::new method invocation. In other words, this Book object has a unique state that is made up of all the objects bound to its instance variables.

我们已经创建或实例化了一个Book对象Book类的一个实例 。 这book有实例变量的束- @title@author@pages 。 该类的特定实例的实例变量绑定到我们传递给::new方法调用的值。 换句话说,此Book对象具有唯一状态,该状态由绑定到其实例变量的所有对象组成。

We can also assign this object to a local variable for safekeeping.

我们还可以将此对象分配给本地变量以进行保管。

triumph_of_the_city = Book.new('Triumph of the City', 'David Glaeser', 338)

How can we access data stored within an object? How can we find the number of pages in our Book object? Right now — our options are limited. If you’re interested in gaining a deeper knowledge of Ruby’s meta-programming, look into Object#instance_variables and Object#instance_variable_get.

我们如何访问存储在对象中的数据? 我们如何在Book对象中找到页数? 目前-我们的选择是有限的。 如果您想对Ruby的元编程有更深入的了解,请查看Object#instance_variablesObject#instance_variable_get

As a general rule of thumb, we cannot directly access an object’s instance variables outside of the class definition — they are private and only accessible within the scope of the object. However, we can define instance methods within the class definition and reference instance variables there. These methods can then be called on an object of that class to access and interact with that object’s instance variables.

根据一般经验,我们不能在类定义之外直接访问对象的实例变量-它们是私有的,只能在对象范围内访问。 但是,我们可以在类定义中定义实例方法,并在那里引用实例变量。 然后可以在该类的对象上调用这些方法,以访问该对象的实例变量并与之交互。

class Book
def initialize(title, author, pages)
@title = title
@author = author
@pages = pages
enddef title
@title
end
end

Here, we’ve added an instance method title, in which we access the instance variable @title. Because this method is available to all Book objects, we can call title like so.

在这里,我们添加了一个实例方法title ,在其中访问实例变量@title 。 因为此方法可用于所有Book对象,所以我们可以像这样调用title

triumph_of_the_city.title

This returns the title of the book.

这将返回书名。

Instance methods that access instance variables are called getter methods, and those that allow a person to modify instance variables are called setter methods. Let’s write a few more getters and a setter method.

访问实例变量的实例方法称为getter方法,而允许人修改实例变量的实例方法称为setter方法。 让我们再写一些getter和setter方法。

class Book
def initialize(title, author, pages)
@title = title
@author = author
@pages = pages
enddef title
@title
enddef author
@author
enddef pages
@pages
enddef pages=(new_pages)
@pages = new_pages
end
end

As you can see, we now have getter methods for title, author, and pages. We also have a setter method for pages. This one might seem strange. It’s a Ruby convention to use = at the end of the name of a setter method. It’s similar to predicate methods ending with ?.

如您所见,我们现在具有用于titleauthorpages getter方法。 我们还有用于pages的setter方法。 这可能看起来很奇怪。 在setter方法名称的末尾使用=是一种Ruby约定。 它类似于以?结尾的谓词方法?

The setter takes one argument, the new value that the user wants to assign to the instance variable. With Ruby’s syntactic sugar, calling a setter method on an object outside of the class definition is a breeze! Let’s say we rip one of the pages out of our book.

设置器采用一个参数,即用户想要分配给实例变量的新值。 使用Ruby的语法糖,在类定义之外的对象上调用setter方法很容易! 假设我们从书中撕下其中一页。

triumph_of_the_city.pages = 337

Ruby allows the act of setting an instance variable of an object to look like assignment. Without the sugar, using the setter method looks like the code below.

Ruby允许将对象的实例变量设置为看起来像赋值的行为。 在没有糖的情况下,使用setter方法看起来像下面的代码。

triumph_of_the_city.pages=(337)

The syntax may take a little while to get used to, but let’s summarize everything we’ve done so far.

语法可能需要一点时间才能习惯,但让我们总结一下到目前为止已经完成的所有工作。

Image for post
Photo by Kaleidico on Unsplash
KaleidicoUnsplash拍摄的照片
  • We defined a class. This class is the template for all objects that are instantiated from it. In the class we dictate the possible attributes and the possible behaviors that objects made from that class will have.

    我们定义了一个类。 此类是从其实例化的所有对象的模板。 在该类中,我们指示该类所创建的对象将具有的可能的属性和可能的​​行为。
  • We instantiated a Book object and gave it some unique values for instance variables.

    我们实例化了一个Book对象,并为它提供了一些实例变量的唯一值。

  • We defined a handful of getter methods to access the instance variables by calling a method on objects outside of the class definition.

    通过在类定义之外的对象上调用方法,我们定义了一些getter方法来访问实例变量。
  • We defined a setter method we can use to re-assign the instance variable pages to a new value.

    我们定义了一个setter方法,可用于将实例变量pages重新分配给新值。

Let’s create one more Book object and bind it to a local variable.

让我们再创建一个Book对象,并将其绑定到局部变量。

walkable_city = Book.new('Walkable City Rules', 'Jeff Speck', 290)

We now have two different instances of the Book class. They have different titles, authors, and numbers of pages. In other words, they are two different Book objects that each have a distinct state.

现在,我们有两个不同的Book类实例。 他们有不同的标题,作者和页数。 换句话说,它们是两个不同的Book对象,每个对象都有不同的状态

*We will forego talking about attr_* methods — Ruby’s short-hand option for creating getters and setters — in this article.

*在本文中,我们将不再讨论attr_*方法(这是Ruby创建getter和setter的捷径)。

实例方法提供功能 (Instance methods give functionality)

Right now, we have two Book objects. We can create a new book by passing arguments into the ::new method call on the Book class. Let’s think about the functionalities available for any Book objects.

现在,我们有两个Book对象。 我们可以通过将参数传递给Book类的::new方法调用来创建一本Book 。 让我们考虑一下可用于任何Book对象的功能。

Image for post
Photo by Joanna Kosinska on Unsplash
乔安娜·科辛斯卡 ( Joanna Kosinska)Unsplash拍摄的照片

Because we wrote getter instance methods for title, author, and pages we can access the values of each of these instance variables from outside the class. We also wrote a setter method for pages, which allows us to change the value bound to @pages in any Book object to any value we desire. We have read and write access for the pages instance variable, while we have read-only access to title and author.

因为我们为titleauthorpages编写了getter实例方法,所以我们可以从类外部访问每个实例变量的值。 我们还为pages写了一个setter方法,该方法允许我们将绑定到任何Book对象中@pages的值更改为@pages任何值。 我们具有对pages实例变量的读写访问权限,而具有对titleauthor read-only访问权限。

With our setter method for @pages, we can alter the number of pages. In fact, a user of our program can even set the number of pages to a String object of 'hello'.

使用我们的@pages的setter方法,我们可以更改页面数。 实际上,我们程序的用户甚至可以将页面数设置为'hello'String对象。

walkable_city.pages = 'hello'

Assigning a String to a variable that is intended to represent a number of pages in a book is nonsensical. Let’s put some restrictions on what a user can do with the @pages instance variable. Rather than allowing a user to set the value to anything they please, let’s only allow them to choose an Integer object.

String分配给旨在代表一本书中许多页面的变量是没有意义的。 让我们对用户可以使用@pages实例变量进行一些限制。 与其允许用户将值设置为任意值,不如让用户选择一个Integer对象。

def pages=(new_pages)
if new_pages.instance_of?(Integer)
@pages = new_pages
else
puts 'Sorry, please enter a number'
end
end

We use a simple if-else conditional that calls Object#instance_of? on the object bound to the passed in parameter new_pages. To the instance_of? call, we pass in the argument of the class name Integer. This is a predicate method that will return true or false, depending whether the class of the calling object matches the passed in argument. If new_pages is bound to anInteger object, we point the instance variable @pages to that Integer. If the user tries to pass in any other type of object, like a String or a Hash, we output an error message to the terminal and do not assign any value to @pages.

我们使用一个简单的if-else条件调用Object#instance_of? 在绑定到传入参数new_pages的对象上。 到instance_of? 调用时,我们传入类名Integer的参数。 这是一个谓词方法,该方法将返回truefalse ,具体取决于调用对象的类是否与传入的参数匹配。 如果将new_pages绑定到Integer对象,则将实例变量@pages指向该Integer 。 如果用户尝试传入任何其他类型的对象(例如StringHash ,我们将向终端输出错误消息,并且不为@pages分配任何值。

We have effectively put one protective measure in place to ensure that @pages will always point to an Integer object. This makes for a more robust program. If we have another instance method that makes use of @pages, we can rest a little more assured that we can expect an Integer and not an object from some other class. This will keep our program from breaking.

我们已经有效地采取了一项保护措施,以确保@pages始终指向一个Integer对象。 这使得程序更健壮。 如果我们还有另一个使用@pages实例方法,我们可以放心一点,我们可以期待一个Integer而不是其他类的对象。 这将防止我们的程序中断。

Now that we have a small, functioning Book class, a couple Book objects with their own unique instance variables and a shared set of methods (just the getters and setter), we can take a look at the main ideas of OOP and its main benefits as a programming paradigm in the second article of this series here.

现在我们有了一个小的,可以运行的Book类,几个Book对象,它们具有自己的唯一实例变量和一组共享的方法(只是getter和setter),我们可以看看OOP的主要思想及其主要优点作为本系列的第二篇文章中一种编程范式这里

翻译自: https://medium.com/@aumi9292/part-1-an-intro-to-oop-d95aa6e445ce

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值