Главная страница Информационный раздел Карта сайта Связь с авторами |
|
![]() Ruby — объектно-ориентированный язык программирования, поэтому знание парадигмы объектно-ориентированного программирования (ООП) является обязательным. Тема объектно-ориентированного программирования достаточно сложна, поскольку в ней переплетаются множество подтем, которые, разделить нельзя, поэтому данная глава будет иметь итерационной подход к изложению материала, то есть мы будем двигаться по спирали захватывая все больший и большый объем информации. Что есть Объектно-ориентированное программирование? Объектно — ориентированное программирование — это программирование основанное на использовании объектов — экземпляров абстрактных типов (классах).
Для начала давайте создадим код, на котором мы будем разбирать примеры,он будет состоять из двух классов: Monkey и Human, где Human, согласно революционной эволюционной теории Чарльза Дарвина наследуется от класса Monkey: class Monkey
def height
def weight
def height=(height)
def weight=(weight)
class Human < Monkey
def name
def name=(name)
m = Monkey.new(120,55)
Что есть Инкупсуляция?Инкапсуляция — это самый большой и жирный кит объектно-ориентированного программирования. Инкапсуляция заключается в том, что присущие функциональному программирования данные и функции над ними превратились в свойства и методы объекта, которые заключены в объект (запаяны в капсулу). Доступ к этим свойствам и методам доступен только через специально определяемые интерфейсы, таким образом скрывается внутреннее устройство объекта. если вы заходите покушать, вам не нужно знать все методы вашего организма по перевариванию пищи,вам не нужно обращаться к языку, чтобы тот чувствовал вкус,к слюнным железам, чтобы те выделяли слюну смачивающую пищу, к нижней челюсти, чтобы та пережевывала пищу до необходимой кондиции, снова к языку и пищеводу, чтобы пища попала в желудок, затем к желудку, чтобы тот обработал пищу желудочным соком и так далее. Все, что вам нужно — это воспользоваться специальным интерфейсом — ртом, положив туда пищу, все, внутренние методы вашего организва запустятся сами этим одним единственным интерфейсом (методом — аксессором, от access — доступ). Ваши свойства, как экземпляра Хомо Сапиенса, это размеры элементов вашего тела, цвет кожи, цвет глаз, родинки и веснушки, ваше имя и фамилия, ваше физическое, духовное и психологическое состояние. Вы хороший, здоровый, темноглазый, бледнолицый, девяносто килограммовый и сто-восьмидесята сантиметровый Иван — и все, что я перечислил — это ваши свойства. Ваши методы — это ходьба, бег, употребление пищи, сон, чтение, писание, программирование и так далее. Свойства к которым можно получить доступ называются открытыми, открыты они не из-за какой-то своей особенности, а из-за того, что для них определены методы — аксессоры. Посмотрте код Monkey и вы увидите там четыре метода аксессора: #weight, #height, #weight= и #height=. Первых два называются ридерами (от read — читать), они занимаются тем, что предоставляют вам текущее значение одноименных свойств объекта @weight и @height. Другие два метода, #height= и #weight= являются аксессорами — врайтерами (от write — писать) и из задача состоит в определении (записи) нового значения свойствам объекта. Без методов аксессоров вы не можете получить доступ к свойствам объекта, вы не можете знать имя девушки, и есть ли у нее парень, пока не воспользуетесь соответствующими методами аксессорами: #name и #has_boyfriend?. Аксессоры read и write также часто называют get и set — аксессорами (от get — получать, set — устанавливать). Расследование что есть НаследованиеНаследование — чуть менее упитанный кит ООП, тем не менее он очень важен. Наследование заключается в эволюции классов. Как человек эволюционировал из обезъяны, так и один класс может наследоваться от другого. Наследование заключается в передаче всей структуры класса Monkey в класс Human, при этом наследование реализуется очень просто, при определении класса Human достаточно дописать < Monkey, что и указывает на наследование класса Human от класса Monkey. Говорят, что Monkey наследует Human, а Human наследуется от Monkey. Говорят, что Monkey — супер класс или родительский класс, а Human — подкласс, субкласс или дочерний класс. На практике это означает, что для Human полностью копируется реализация класса Monkey. Такое копирование и есть Наследованием. Наследование — очень полезная вещь, так как: предоставляет возможность повторного использования кода, спасает от повторений в коде. Скажем имея класс Human, мы можем наследоваться от него классами WhiteHuman и BlackHuman, которые будут иметь абсолютно одиинаковые свойства, за исключением цвета кожи и формы носа. Вместо написания двух новых классов, вы просто наследуетесь ими от базового класса — Human дополняя его новыми свойствами и методами, либо переписывая старые. class BlackHuman < Human
def skin_color
def skin_color=(skin_color)
На случай, если темнокожего человека зовут Майкл Джексон, мы определяем метод-аксессор #skin_color=, который позволяет изменить цвет кожи. Полиморфизм — все течет, все меняетсяПолиморфизм — самый щуплый кит объектно-ориентированного программирования, который тесно связан с китом наследования и делает наследование еще более мощным. Полиморфизм (поли — много, морфе — форма) заключается в том, что наследуясь, в классе — потомке (дочернем классе или подклассе или субклассе или …) вы можете переопределять унаследованные свойства и методы. Во всех трех примерах выше имеется метод #initialize. Метод #initialize, согласно договоренности, является тем методом, что автоматически выполняется при создании нового экземпляра класса, такие методы еще называют методами — конструкторами. В классах Monkey и Human данный метод занимается тем, что принимает данные переданные в метод .new при создании нового объекта и устанавливает эти данные в свойства создаваемого объекта. Поскольку у экзмепляров классов Monkey и Human набор свойств разный, то и разное количечество аргументов должно быть принято, от чего следует в классе Human переопределить данный метод таким образом, чтобы он мог задавать дополнительные свойства. В классе BlackHuman мы также переопределяем метод #initialize, однако он сам устанавливает свойству @skin_color по умолчанию значение :black. В обоих классах Human и BlackHuman метод #initialize снабжен выражением super. Super — это очень полезное выражение, которое позволяет в контексте метода вызывать одноименный метод из родительского класса, другими словами, super позволяет реализовать что-то вроде «наследования методов» при котором мы в контексте переопределенного метода, вызываем старый метод и дополняем его. Все эти операции по переопределению и носят имя полиморфизм. Области видимости и типы переменныхНевозможно объяснять более-менее сложные вещи не объяснив о том, что такое область видимости и какие переменный бывают.
Создание объектовВ Ruby существут предопределенные типы данных, которые были рассмотрены в прошлой главе и абстрактные — то, что мы рассматриваем в данной главе RubyDev Ruby Tutorial. 5.object_id #=> 11
Просто используя тот или иной литерал, мы автоматически создаем соответствующий литералу объект. Работая с абстрактными типами данных, нам необходимо явно определять объект при помощи метода .new класса, примеры: m = Monkey.new(120,55)
m и h являются объектами, соответственно, классов Monkey и Human, что означает, что они имеют тип Monkey и Human. На самом деле m и h являются всеголишь переменными ссылающимися на реальные объекты в памяти компьютера, которые не имеют имен, но имеют уникальные идентификаторы объектов, по которым к ним происходит обращение. Несмотря на это m и h, для простоты можно также называть объектами. Создавая объект (экземпляр класса) нам необходимо воспользоваться методом .new. Метод .new принимает аргументы для создания класса, которые затем могут быть использованы в методе #initialize и создает новый объект. Методы классов и методы объектов Вы наверняка заметили, что в данном учебнике перед именами одних методов я ставлю знак #, а перед именами других я ставлю точку. Это такая договоренность, согласно которой имена методов вне текста программы начинаются с # если метод принадлежит объекту и с . , если метод принадлежит классу. Метод класса отличается от метода объекта тем, что приемником метода класса является класс, а приемником метода экземпляра класса является экземпляр класса (объект). Хочу заметить, что в Ruby даже сами классы являютя объектами. Отличие классов от объектов заключается в том, что каждый класс является экземпляром базового класса Class. Любой метод объявленный следущим образом: def method_name()
является методом экземпляра класса. Для того, чтобы объявить метод класса, вам необходимо использовать следущую конструкцию: def self.method_name()
class BlackHuman < Human class << self
def initialize(height, weight, name)
def skin_color
def skin_color=(skin_color)
bh = BlackHuman.new(180,90,"John")
puts BlackHuman.obj_count # 3 Как видно из примера, вызов методов класса не отличается от вызова методов объекта, единственное отличие — это приемник метода. |
|