Pull to refresh

Покорим Ruby вместе! Капля четвертая

Programming *
Собираем капли дальше (1, 2, 3). В этот раз узнаем о реализации ООП в Руби.

Классы, объекты, методы


Вместо того, чтобы углубляться дальше в синтаксис Ruby, отставим циклы, типы, модули и др. — мы вернёмся к ним позже. Сейчас же мы посмотрим, как создавать классы, объекты и методы.

Как и в других объектных языках объекты определяются классом. Например этот класс определяет собак (о_0):

class Dog 
   def set_name( aName ) 
     @myname = aName 
   end 
end

Ну а чем вам собаки — не класс? ;) Смотрим код. Определение класса начинается с ключевого слова class и названия самого класса, которое обязано должно начинаться с большой буквы. В классе определен метод set_name (def...end), который будет называть каждый объект-собаку. Он берёт входящий аргумент aName и назначает его значение переменной @myname.

Переменные, начинающиеся с @, — это переменные экземпляра класса. Важно то, что значение такой переменной доступно только внутри экземпляра, к которому она принадлежит. Создадим два объекта (две конкретные собаки) с помощью метода new:

moya = Dog.new 
tvoya = Dog.new

Напоминаю и запоминаем: класс называем только с большой буквы, объект — только со строчной. Используем метод set_name, чтобы назвать собак:

moya.set_name( 'Lassie' ) 
tvoya.set_name( 'Rex' ) 

Как теперь вывести клички собак? Мы не можем «вытащить» переменную @name из объекта, так как внутренние данные объекта известны только ему (см. выше). Это основной принцип ООП: данные объекта приватны; это называется скрытие данных и является частью принципа инкапсуляции.

Для решения этой задачки просто добавим новый метод в класс, который будет выводить переменную:

def get_name 
   return @myname 
end

Слово return необзательно, Руби возвратит последнее полученное значение, однако писать его — хорошая привычка.

Заставим собаку лаять (для этого напишем еще один метод) и соберём всё в кучу:

class Dog    
   def set_name( aName ) 
     @myname = aName 
   end 
 
   def get_name 
     return @myname 
   end 
 
   def gav 
     return 'r-r-r-r!' 
   end 
end

dog1 = Dog.new 
dog1.set_name( 'Fido' ) 
puts(dog1.get_name) 
puts(dog1.gav) 

Представим, что у нас есть два класса (например, кошки и собаки), в каждом определено по объекту (конкретные кот и пёс) и методу с одинаковыми названиями («говорить», но кот мяукает, а пёс лает). Получается, что на один и тот же метод объекты реагируют по-разному. Возможность иметь несколько классов, содержащих одноименные методы, называется полиморфизм. Узнали… и забыли это грозное слово.

Атрибуты


Для нашей задачи есть другой подход — создадим необходимые методы с помощью атрибутов класса. Усложним поставленное задание и создадим зоопарк ;)

class Cat
   attr_accessor :name, :age, :gender, :color
end
class Dog
   attr_accessor :name, :age, :gender, :color
end
class Snake
   attr_accessor :name, :age, :gender, :color, :length
end

Рассмотрим вторую строку. Она предоставляет три атрибута для класса Cat. Каждая кошка имеет свою кличку, возраст, пол и окрас — и код создает эти атрибуты. _accessor означает «сделайте эти атрибуты доступными для создания и изменения».

Создадим объект и применим атрибуты:

cat_object = Cat.new
cat_object.name = "Pussy"
........................
puts cat_object.name


Наследование


Посмотрев на последний код с объявлением трёх классов, легко заметить, что они предельно похожи. Лишь у змеи дополнительно определена длина. Вспомним принципы программирования на Ruby из первой капли. Один из них: DRY (Don't repeat yourself), который означает, что мы должны писать необходимый код только один раз, а у нас сплошные повторения. Нам просто необходимо обратить внимание на одну из лучших возможностей ООП: наследование.

Наследование позволяет разным классам соотноситься друг с другом и группироваться по схожестям в структуре. В нашем примере коты, собаки, змеи — всё это питомцы (pets). Так почему бы нам не создать класс Pet, который будет «родительским» для остальных, которые, в свою очередь, будут наледовать общие для всех питомцев свойства? Пишем:

class Pet
   attr_accessor :name, :age, :gender, :color
end
class Cat < Pet
end
class Dog < Pet
end
class Snake < Pet
   attr_accessor :length
end

Принцип и правила объявления наследованных классов, думаю, понятны, теперь попробуйте создать объекты, задать параметры и вывести результат. Заметим, что более простые классы стоят выше сложных в иерархии классов.

Эпилог


В прошлой капле мы с вами выяснили, что такое ООП, в этой — научились применять знания в Ruby, узнали несколько замудренных слов, познакомились с переменными экземпляра и атрибутами класса. Еще одна капля в наш стакан ;)

Благодарю Хью Колинборна и Питера Купера за замечательные примеры для наших капель. Коментарии и замечания как всегда принимаются! До встречи!
Tags:
Hubs:
Total votes 54: ↑47 and ↓7 +40
Views 31K
Comments Comments 66