Само имя класса - это глобальная константа, поэтому оно должно начинаться с прописной буквы. Определение класса может содержать константы, переменные класса, методы класса, переменные экземпляра и методы экземпляра. Данные уровня класса доступны всем объектам этого класса, тогда как данные уровня экземпляра доступны только одному объекту
Попутное замечание: строго говоря, классы в Ruby не имеют имен.Class
(поскольку в Ruby Class
— это класс). Ясно, что на один и тот же класс могут ссылаться несколько констант, и их можно присваивать переменным точно так же, как мы поступаем с любыми другими объектами (поскольку в Ruby Class
— это объект). Если вы немного запутались, не расстраивайтесь. Удобства ради новичок может считать, что в Ruby имя класса — то же самое, что в C+ +.
Вот как определяется простой класс:
class Friend
@@myname = 'Эндрю' # переменная класса
def initialize(name, sex, phone)
@name, @sex, @phone = name, sex, phone
# Это переменные экземпляра
end
def hello # метод экземпляра
puts 'Привет, я #{@name}.'
end
def Friend.our_common_friend # метод класса
puts 'Все мы друзья #{@@myname}.'
end
end
f1 = Friend.new('Сюзанна','F','555-0123')
f2 = Friend.new('Том','M','555-4567')
f1.hello # Привет, я Сюзанна.
f2.hello # Привет, я Том.
Friend.our_common_friend # Все мы друзья Эндрю.
Поскольку данные уровня класса доступны во всем классе, их можно инициализировать в момент определения класса. Если определен метод с именем initialize
, то гарантируется, что он будет вызван сразу после выделения памяти для объекта. Этот метод похож на традиционный конструктор, но не выполняет выделения памяти. Память выделяется методом new
, а освобождается неявно сборщиком мусора.
Теперь взгляните на следующий фрагмент, обращая особое внимание на методы getmyvar
, setmyvar
и myvar=
:
class MyClass
NAME = 'Class Name' # константа класса
@@count = 0 # инициализировать переменную класса
def initialize # вызывается после выделения памяти для объекта
@@count += 1
@myvar = 10
end
def MyClass.getcount # метод класса
@@count # переменная класса
end
def getcount # экземпляр возвращает переменную класса!
@@count # переменная класса
end
def getmyvar # метод экземпляра
@myvar # переменная экземпляра
end
def setmyvar(val) # метод экземпляра устанавливает @myvar
@myvar = val
end
def myvar=(val) # другой способ установить @myvar
@myvar = val
end
end
foo = MyClass.new # @myvar равно 10
foo.setmyvar 20 # @myvar равно 20
foo.myvar =30 # @myvar равно 30
Здесь мы видим, что getmyvar
возвращает значение переменной @myvar
, а setmyvar
устанавливает его. (Многие программисты говорят о методах чтения и установки). Все это работает, но не является характерным способом действий в Ruby. Метод myvar=
похож на перегруженный оператор присваивания (хотя, строго говоря, таковым не является); это более удачная альтернатива setmyvar
, но есть способ еще лучше.
Класс Module
содержит методы attr
, attr_accessor
, attr_reader
и attr_writer
. Ими можно пользоваться (передавая символы в качестве параметров) для автоматизации управления доступом к данным экземпляра. Например, все три метода getmyvar
, setmyvar
и myvar=
можно заменить одной строкой в определении класса:
attr_accessor :myvar
При этом создается метод myvar
, который возвращает значение @myvar
, и метод myvar=
, который позволяет изменить значение той же переменной. Методы attr_reader
и attr_write
r создают соответственно версии методов доступа к атрибуту для чтения и для изменения.
Внутри методов экземпляра, определенных в классе, можно при необходимости пользоваться переменной self
. Это просто ссылка на объект, от имени которого вызван метод экземпляра.
Для управления видимостью методов класса можно пользоваться модификаторами private
, protected
и public
. (Переменные экземпляра всегда закрыты, обращаться к ним извне класса можно только с помощью методов доступа.) Каждый модификатор принимает в качестве параметра символ, например :foo
, а если он опущен, то действие модификатора распространяется на все последующие определения в классе. Пример:
class MyClass