Ruby Объектно-ориентированный
Ruby — это чистый объектно-ориентированный язык, и в Ruby всё принимает форму объектов. Каждое значение в Ruby является объектом, даже самые примитивные вещи: строки, числа, и даже true и false являются объектами. Сам класс также являетсяобъектом, который являетсяClassэкземпляром класса Class. В этой главе будут объяснены все основные возможности, связанные с объектно-ориентированным программированием на Ruby.
Классы используются для задания формы объектов. Они объединяют представление данных и методы, организуя данные в аккуратный пакет. Данные и методы в классе называются членами класса.
Определение класса Ruby
Когда вы определяете класс, вы фактически определяете шаблон для типа данных. Это фактически не определяет никаких данных, а скорее определяет, что означает имя класса, то есть из чего будут состоять объекты класса и какие операции можно выполнять с объектом.
Определение класса начинается с ключевого словаclass, за которым следуетимя класса, и наконец заканчиваетсяendразделитель для обозначения конца определения класса. Например, мы используем ключевое слово class для определения класса Box, как показано ниже:
По соглашению имя должно начинаться с заглавной буквы. Если оно содержит несколько слов, пишите первую букву каждого слова заглавной, но без разделителей между ними (например, CamelCase).
Определение объектов Ruby
Классы предоставляют шаблон для объектов, поэтому по сути объекты создаются на основе класса. Мы используемnewкак ключевое слово для объявления объектов класса. Следующий оператор объявляет два объекта класса Box:
Метод initialize
initializeМетод является стандартным методом класса Ruby, служащим конструктором класса, и аналогичен принципу работыконструкторав других объектно-ориентированных языках программирования. Когда вы хотите инициализировать некоторые переменные класса при создании объекта, метод initialize пригодится. Этот метод принимает ряд параметров; как и другие методы Ruby, при его использовании вы должны поставитьdefключевое слово перед ним, как показано ниже:
Переменные экземпляра
Переменные экземпляраявляются атрибутами класса. Когда объекты создаются с помощью класса, они становятся атрибутами объектов. Атрибуты каждого объекта назначаются отдельно и не разделяют значения с другими объектами. Внутри класса эти атрибуты доступны с помощью оператора @; вне класса доступ к ним осуществляется с помощью методов, называемыхметодами доступа, которые относятсякpublicметодам. Ниже мы возьмём класс, определённый выше,Boxв качестве примера и используем @width и @height как переменные экземпляра класса Box.
Методы доступа (getter) и установки (setter)
Чтобы читать переменные, определённые в классе, извне класса, мы можем определить методы доступа (getter) для доступа к ним. В следующем примере демонстрируется использование методов доступа:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
盒子宽度 : 10 盒子高度 : 20
Подобно методам доступа, используемым для доступа к значениям переменных, Ruby предоставляет способ передавать параметры переменным, определённым в классе, извне класса, так называемыеметоды установки, определяемые следующим образом:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
盒子宽度 : 30 盒子高度 : 50
Поскольку оба метода очень часто используются, Ruby определяетattr_accessor :variable_name、attr_reader :variable_name、attr_writer :variable_nameтри метода объявления атрибутов. Среди них:accessor=reader+writer。
Также обратите внимание: перед именем переменной должен быть префикс:, а между именами переменных используйте,для разделения.
Методы экземпляра
Методы экземпляраопределяются так же, как и другие методы, с помощьюdefключевого слова, но они могут использоваться только через экземпляры класса, как показано в примере ниже. Их функции не ограничиваются доступом к переменным экземпляра; они также могут выполнять множество других задач по мере необходимости.
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
Area of the box is : 200
Методы класса & переменные класса
Переменные класса— это переменные, общие для всех экземпляров класса. Иными словами, переменные класса доступны всем экземплярам объектов. Переменные класса имеют префикс из двух символов @ (@@). Переменные класса должны быть инициализированы в определении класса, как показано в примере ниже.
Методы классаопределяются с помощью ключевого словаdef self.methodname(), и методы класса заканчиваются разделителем end. Методы класса можно вызывать, используя формуclassname.methodnameс именем класса, как показано в примере ниже:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
Box count is : 2
Метод to_s
Любой определяемый вами класс имеет экземплярный методto_s, возвращающий строковое представление объекта. Ниже приведён простой пример, представляющий объекты Box на основе ширины и высоты:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
String representation of box is : (w:10,h:20)
Управление доступом
Ruby предоставляет вам три уровня защиты методов экземпляра, а именноpublic, private, or protected. Ruby не применяет контроль доступа к переменным экземпляра и класса.
- Публичные методы:Публичные методы могут быть вызваны любым объектом. По умолчанию методы являются публичными, кроме метода initialize, который всегда приватный.
- Приватные методы:Приватные методы не могут быть доступны или просмотрены извне класса. Только методы класса могут получать доступ к приватным членам.
- Защищённые методы:Защищённые методы могут вызываться только объектами класса и его подклассов. Доступ также может быть осуществлён только внутри класса и его подклассов.
Ниже приведён простой пример, демонстрирующий синтаксис этих трёх модификаторов:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат. Здесь первый вызов метода завершается успешно, но второй метод вызывает проблему.
Area of the box is : 200 test.rb:42: protected method `printArea' called for # <Box:0xb7f11280 @height=20, @width=10> (NoMethodError)
Наследование классов
Наследование — одна из наиболее важных концепций объектно-ориентированного программирования. Наследование позволяет определять класс на основе другого класса, что упрощает создание и поддержку приложений.
Наследование помогает повторно использовать код и обеспечивает быстрое выполнение. К сожалению, Ruby не поддерживает множественное наследование, но Ruby поддерживаетмиксинымиксины. Миксины — это как особая реализация множественного наследования, в которой наследуется только интерфейсная часть.
При создании класса программист может напрямую указать, что новый класс наследует члены существующего класса, избегая необходимости писать новые элементы данных и функции-члены с нуля. Этот существующий класс называетсябазовым классом или родительским классом, а новый класс называетсяпроизводным классом или подклассом。
Ruby также предоставляет концепцию создания подклассов, которая является наследованием. Следующий пример объясняет эту концепцию. Синтаксис расширения класса очень прост. Просто добавьте символ < и имя родительского класса в инструкцию class. Например, следующее определяет классBigBoxДаBoxподкласс:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
Big box area is : 200
Перегрузка методов
Хотя в производном классе можно добавить новую функциональность, иногда может потребоваться изменить поведение метода, уже определённого в родительском классе. В этом случае можно оставить имя метода без изменений и переопределить функциональность метода, как показано в следующем примере:
Пример
Попробуйте »
Вывод приведенного выше примера:
Big box area is : 200
Перегрузка операторов
Мы хотим использовать оператор + для выполнения векторного сложения двух объектов Box, использовать оператор * для умножения ширины и высоты Box, а также использовать унарный оператор - для отрицания ширины и высоты Box. Ниже приведена версия класса Box с определениями математических операторов:
Замораживание объектов
Иногда мы хотим предотвратить изменение объектов. В классе Object метод freeze может этого добиться, фактически превращая объект в константу. Любой объект можно заморозить, вызвавObject.freezefreeze. Замороженный объект нельзя изменить, то есть вы не можете изменять его переменные экземпляра.
Вы можете использоватьObject.frozen?метод, чтобы проверить, был ли заморожен данный объект. Если объект заморожен, этот метод возвращает true; в противном случае он возвращает false. Следующий пример поясняет эту концепцию:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
Box object is frozen object
test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
from test.rb:39
Константы класса
Вы можете определить константу внутри класса, присвоив переменной непосредственно числовое или строковое значение. Константы не нуждаются в использовании @ или @@. По соглашению имена констант пишутся с заглавной буквы.
После того как константа определена, вы не можете изменить её значение. Вы можете получить доступ к константе непосредственно внутри класса, так же как к переменной, но если вы хотите получить доступ к константе вне класса, вы должны использоватьclassname::constant::, как показано в следующем примере.
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
Area of the box is : 200 TATA Inc Box weight is: 10
Константы класса могут наследоваться, а также могут быть переопределены, как методы экземпляра.
Создание объектов с помощью allocate
Может возникнуть ситуация, когда вы хотите создать объект, не вызывая конструктор объектаinitialize, т. е. не используя метод new для создания объекта. В этом случае вы можете вызвать allocate, чтобы создать неинициализированный объект, как показано в следующем примере:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
Area of the box is : 200 test.rb:14: warning: instance variable @width not initialized test.rb:14: warning: instance variable @height not initialized test.rb:14:in `getArea': undefined method `*' for nil:NilClass (NoMethodError) from test.rb:29
Информация о классе
self в Ruby и this в Java имеют сходства, но также сильно различаются. В Java методы вызываются внутри методов экземпляра, поэтому this обычно указывает на текущий объект. Код Ruby выполняется строка за строкой, поэтому self имеет разные значения в разных контекстах. Давайте посмотрим на следующий пример:
Пример
Попробуйте »
Когда приведённый выше код выполняется, он выдаёт следующий результат:
Class of self = Class Name of self = Box
Это означает, что определение класса может быть выполнено, если рассматривать класс как текущий объект, а также означает, что методы в метаклассе и родительском классе доступны во время выполнения определения метода.
Другие расширения