Ruby — один из самых популярных языков, используемых в сети. Недавно мы начали новую серию скринкастов здесь, на Nettuts +, которая познакомит вас с Ruby, а также с отличными фреймворками и инструментами, которые сопровождают разработку на Ruby. В этой главе мы рассмотрим создание наших собственных классов Ruby.
Наверстать
- Часть 1. Установка Ruby и начало работы
- Часть 2. Переменные, типы данных и файлы
- Часть 3: Работа с классами
Посмотреть скринкаст
Модификация пустого объекта
Во второй главе мы узнали, как добавлять методы к уже существующему объекту. Если мы хотим начать с пустого объекта, который мы можем затем дополнить методами и свойствами, мы можем просто создать экземпляр класса Object
.
1
2
3
4
5
|
o = Object.new
def o.my_method
1 + 1
end
o.my_method # => 2
|
Как насчет недвижимости? В Ruby есть переменные экземпляра (переменные, которые получает каждый экземпляр объекта); переменная экземпляра начинается со знака «at» ( @
). Вы можете получить и установить эти переменные экземпляра, создав функции специально для этой цели.
01
02
03
04
05
06
07
08
09
10
|
def o.set_name ( name )
@name = name
end
def o.get_name
@name
end
o.set_name «Andrew»
o.get_name # => Andrew
|
Обратите внимание, что переменная @name
нигде не должна быть инициализирована. Ruby позаботится о том, чтобы это было организовано для вас Теперь мы можем установить и получить переменные экземпляра @name
. Тем не менее, не слишком ли уродливо использовать set_name
и get_name
для свойств? Делать что-то вроде o.name = "Andrew"
для записи и o.name
для чтения было бы намного более естественным. Мы увидим, как это сделать через минуту; но сейчас давайте начнем создавать собственный класс.
Создание класса
Создать класс довольно просто. Просто используйте следующий синтаксис. На этом уроке мы создадим довольно бесполезный класс Person
:
1
2
3
|
class Person
end
|
Опять супер-просто. Давайте начнем заполнять его.
Создание свойств
Мы видели, как создавать свойства: они просто обертки методов для переменных экземпляра. Тем не менее, мы хотим, чтобы они действовали так, как вы ожидаете от свойств. Это легко для метода get:
1
2
3
|
def name
@name
end
|
Поскольку мы находимся внутри класса, нам не нужно указывать имя объекта в сигнатуре метода; просто название метода будет делать. Когда мы создадим экземпляр класса Person
скажем, p1
мы сможем вызвать его обычным p1.name
.
Но как мы можем улучшить внешний вид установки переменной @name
?
Руби дает нам невероятное количество сахара, чтобы сделать это действительно круто. Проверь это:
1
2
3
|
def name= name
@name = name
end
|
Хорошо, и что? Таким образом, мы пишем p1.name=("joe")
или, по крайней мере, p1.name="joe"
, потому что скобки не требуются. Это намного лучше? Ну, вот классная часть: вы можете поставить пробелы, и Руби не пропустит удар:
1
|
p1.name = «joe»
|
Теперь мы можем писать и читать переменные нашего экземпляра так, как вы ожидаете, что свойства будут прочитаны.
Но это становится еще лучше. Установка свойств с помощью таких методов дает вам возможность сделать что-то со значением, которое передает пользователь вашего класса — нечто большее, чем просто присвоить его переменной экземпляра, если это подходит для вашего класса. Тем не менее, есть большая вероятность, что большую часть времени вы будете делать то же, что и здесь: просто установите или получите переменные экземпляра. В этом случае Ruby делает это еще проще. Просто добавьте это в начало вашего класса:
1
|
attr_accessor :name, :age, :your_properties_here
|
Передайте attr_accessor
имена ваших свойств в виде символов. Это создаст для вас методы var
и var=
. Затем вы сможете использовать @
версии везде, где вам нужно в вашем коде.
Если вам нужны свойства только для чтения или только для записи, вы можете использовать attr_reader
или attr_writer
, соответственно. Конечно, если вы используете, скажем, attr_writer
, вы можете при необходимости создать собственный метод чтения.
Метод создания экземпляра
Мы видели, как создавать методы экземпляра; не забудьте, что вы можете использовать эти значения свойств, если вам нужно:
1
2
3
|
def greet
«#{@name} says, ‘Hello there!'»
end
|
Создание конструктора
Часто вы захотите выполнить некоторый код настройки при создании экземпляра класса. Это делается в функции конструктора. В Ruby функция конструктора называется initialize
. Поп это в верхней части нашего класса Person
:
1
2
3
4
5
|
def initialize (name, age, job = ‘unemployed’)
@name = name
@age = age
@job = job
end
|
Как видите, инициализация принимает три параметра. Третий, job
, является необязательным, потому что мы дали ему значение по умолчанию. Конечно, это работает для любой функции, а не только для функции конструктора. Теперь, когда мы хотим создать экземпляр лица, мы должны сделать следующее:
1
2
|
joe = Person.new(«Joe», 35, «plumber»)
jill = Person.new «Jill», 14
|
Создание частных методов
Закрытые методы — это функции, которые могут вызываться только другими функциями в классе; они не подвержены воздействию внешнего мира. Обычный способ создания закрытых методов заключается в следующем: под всем вашим открытым кодом (методы instance и class) добавьте ключевое слово private
. Любые функции, которые следуют за этим ключевым словом, являются частными.
1
2
3
4
5
6
7
|
# instance and class methods above
private
def get_real_weight
@weight
end
end # of the class
|
Если вы попытаетесь вызвать этот метод для экземпляра Person
, он не будет работать.
Создание методов и переменных класса
Методы и свойства класса — это функции и переменные, которые доступны не из экземпляров класса, а из самого класса. Например, давайте создадим метод класса, который возвращает количество созданных нами экземпляров Person
.
Сначала нам нужно создать переменную класса, которая будет содержать количество созданных нами экземпляров Person
. Переменные класса имеют префикс с двумя знаками at. Итак, добавьте это в ваш класс, желательно под строчкой attr_ *:
1
|
@@count = 0
|
Теперь, когда мы создаем нового Person
, мы хотим увеличить эту переменную. Что работает каждый раз, когда мы делаем Person
? initialize
, конечно; поэтому обновите его соответственно. Теперь это выглядит так:
1
2
3
4
5
6
7
|
def initialize (name, age, job = ‘unemployed’)
@name = name
@age = age
@job = job
@@count += 1
end
|
Затем, конечно, мы должны создать метод класса:
1
2
3
|
def self.count
@@count
end
|
Теперь, попробуйте это:
1
2
3
4
5
|
joe = Person.new(«Joe», 35, «plumber»)
jill = Person.new(«Jill», 13)
bob = Person.new «Bob», 70
Person.count # => 3
|
Примечание. В Ruby на самом деле нет методов класса (или статических методов, как их называют некоторые языки). На самом деле под поверхностью происходит довольно крутое «волшебство», которое делает их похожими на классовые методы. Мы углубимся в это — обычно это называется метапрограммирование — в следующей главе.
Вывод
Вот и все на сегодня; если у вас есть какие-либо вопросы, дайте мне знать в комментариях. В следующий раз мы рассмотрим много общих методов для встроенных классов Ruby.
PS — Я играл с настройками звука на моем микрофоне. Достаточно ли громка в этом скринкасте или должна быть выше?