Статьи

Рубин для новичков: работа с классами

Ruby — один из самых популярных языков, используемых в сети. Недавно мы начали новую серию скринкастов здесь, на Nettuts +, которая познакомит вас с Ruby, а также с отличными фреймворками и инструментами, которые сопровождают разработку на Ruby. В этой главе мы рассмотрим создание наших собственных классов Ruby.




Во второй главе мы узнали, как добавлять методы к уже существующему объекту. Если мы хотим начать с пустого объекта, который мы можем затем дополнить методами и свойствами, мы можем просто создать экземпляр класса 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 — Я играл с настройками звука на моем микрофоне. Достаточно ли громка в этом скринкасте или должна быть выше?