Ruby — це повністю об'єктно-орієнтована мова програмування (OOP), що означає, що майже все в Ruby є об'єктом. Парадигма OOP Ruby дозволяє легко писати чистий, багаторазовий і модульний код. У цьому блозі ми розглянемо основи об'єктно-орієнтованого програмування в Ruby, включаючи класи, об'єкти, спадкування, поліморфізм, інкапсуляцію та модулі — все це з детальними прикладами.
1. Що таке об'єктно-орієнтоване програмування?
OOP — це парадигма програмування, яка організовує код у вигляді об'єктів. Об'єкти є екземплярами класів, які інкапсулюють дані (атрибути) та поведінку (методи). Модель OOP Ruby надає ключові функції:
- Інкапсуляція: Приховування внутрішнього стану об'єктів та вимога, щоб усі взаємодії здійснювались через методи.
- Спадкування: Можливість класу наслідувати інший клас, отримуючи його методи та атрибути.
- Поліморфізм: Використання загального інтерфейсу для різних типів даних або класів.
2.
Класи та об'єкти
Клас — це шаблон для створення об'єктів. Об'єкти — це конкретні екземпляри класу. В Ruby створення та використання об'єктів є інтуїтивно зрозумілим.
Приклад коду:
# Визначаємо клас
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
"Hello, my name is #{@name} and I am #{@age} years old."
end
def birthday
@age += 1
"Happy Birthday! #{@name} is now #{@age} years old."
end
end
# Створення об'єктів
person1 = Person.new("Alice", 30)
person2 = Person.new("Bob", 25)
# Виклик методів об'єктів
puts person1.greet # Виведення: Hello, my name is Alice and I am 30 years old.
puts person2.birthday # Виведення: Happy Birthday! Bob is now 26 years old.
3. Спадкування
Спадкування дозволяє класу (дитині) успадковувати атрибути та методи від іншого класу (батька).
Ruby використовує символ <
, щоб позначити спадкування.
Приклад коду:
# Батьківський клас
class Animal
attr_reader :name
def initialize(name)
@name = name
end
def speak
"#{@name} makes a sound."
end
end
# Дитячий клас
class Dog < Animal
def speak
"#{@name} barks."
end
end
# Дитячий клас
class Cat < Animal
def speak
"#{@name} meows."
end
end
# Створення об'єктів
dog = Dog.new("Rex")
cat = Cat.new("Whiskers")
puts dog.speak # Виведення: Rex barks.
puts cat.speak # Виведення: Whiskers meows.
4. Поліморфізм
Поліморфізм дозволяє об'єктам різних класів відповідати на той самий виклик методу своїм унікальним способом.
Це досягається через перевизначення методів.
Приклад коду:
class Employee
def initialize(name, salary)
@name = name
@salary = salary
end
def details
raise "Цей метод повинен бути перевизначений підкласами."
end
end
class Manager < Employee
def details
"#{@name} is a Manager earning $#{@salary} per year."
end
end
class Developer < Employee
def details
"#{@name} is a Developer earning $#{@salary} per year."
end
end
# Використовуємо поліморфізм
employees = [Manager.new("Alice", 100000), Developer.new("Bob", 80000)]
employees.each do |employee|
puts employee.details
end
# Виведення:
# Alice is a Manager earning $100000 per year.
# Bob is a Developer earning $80000 per year.
5. Інкапсуляція
Інкапсуляція обмежує доступ до внутрішнього стану об'єкта і дозволяє змінювати його лише через визначені методи.
Ruby досягає цього за допомогою приватних або захищених методів.
Приклад коду:
class BankAccount
def initialize(balance)
@balance = balance
end
# Публічний метод для показу балансу
def show_balance
"Your balance is $#{@balance}."
end
# Публічний метод для поповнення рахунку
def deposit(amount)
if valid_transaction?(amount)
@balance += amount
"Deposited $#{amount}. New balance is $#{@balance}."
else
"Invalid transaction."
end
end
private
# Приватний метод для перевірки транзакцій
def valid_transaction?(amount)
amount > 0
end
end
account = BankAccount.new(1000)
puts account.show_balance # Виведення: Your balance is $1000.
puts account.deposit(500) # Виведення: Deposited $500. New balance is $1500.
puts account.deposit(-100) # Виведення: Invalid transaction.
6. Модулі та міксини
Модулі групують багаторазові методи і можуть бути змішані в класи за допомогою include
або extend
.
Вони надають спосіб поділитися поведінкою між кількома класами.
Приклад коду:
module Flyable
def fly
"#{self.class} is flying!"
end
end
class Bird
include Flyable
end
class Plane
include Flyable
end
bird = Bird.new
plane = Plane.new
puts bird.fly # Виведення: Bird is flying!
puts plane.fly # Виведення: Plane is flying!
7.
Складний приклад: реальне застосування
Давайте створимо бібліотечну систему, щоб продемонструвати всі принципи об'єктно-орієнтованого програмування разом.
Приклад коду:
module Searchable
def find_by_title(title)
@items.find { |item| item.title == title }
end
end
class Library
include Searchable
def initialize
@items = []
end
def add_item(item)
@items << item
end
def list_items
@items.map(&:details).join("\n")
end
end
class Book
attr_reader :title
def initialize(title, author)
@title = title
@creator = author
end
def details
"Book: #{@title} by #{@creator}"
end
end
class DVD
attr_reader :title
def initialize(title, director)
@title = title
@creator = director
end
def details
"DVD: #{@title} directed by #{@creator}"
end
end
library = Library.new
book = Book.new("1984", "George Orwell")
dvd = DVD.new("Inception", "Christopher Nolan")
library.add_item(book)
library.add_item(dvd)
puts library.list_items
# Виведення:
# Book: 1984 by George Orwell
# DVD: Inception directed by Christopher Nolan
item = library.find_by_title("1984")
puts item.details # Виведення: Book: 1984 by George Orwell
Висновок
Особливості об'єктно-орієнтованого програмування Ruby надають інструменти для створення модульного, багаторазового та підтримуваного коду.
Оволодіваючи класами, об'єктами, спадкуванням, поліморфізмом, інкапсуляцією та модулями, ви зможете повною мірою використовувати потенціал Ruby для створення масштабованих застосунків. Практикуйте ці концепції та експериментуйте зі своїми проектами, щоб поглибити розуміння!
Перекладено з: Understanding Object-Oriented Programming in Ruby