Виртуальные методы — это методы, которые предназначены для переопределения в подклассах. В отличие от некоторых строго типизированных языков, в Ruby все методы по умолчанию являются виртуальными, так как язык поддерживает полиморфизм и динамическую диспетчеризацию.
class Animal
def speak
"Звук животного"
end
end
class Dog < Animal
def speak
"Гав-гав!"
end
end
class Cat < Animal
def speak
"Мяу!"
end
end
animals = [Animal.new, Dog.new, Cat.new]
animals.each { |a| puts a.speak }
# Вывод:
# Звук животного
# Гав-гав!
# Мяу!
Вызов метода определяется в runtime на основе фактического класса объекта:
def make_animal_speak(animal)
animal.speak # Конкретный метод определяется при выполнении
end
В отличие от Java или C#, в Ruby нет ключевых слов virtual
или override
:
class Parent
def method
"Родитель"
end
end
class Child < Parent
def method # Автоматически переопределяет родительский
super + " -> Ребенок"
end
end
Можно изменить не только реализацию, но и сигнатуру метода:
class Calculator
def add(a, b)
a + b
end
end
class SmartCalculator < Calculator
def add(*numbers)
numbers.sum
end
end
Ruby хранит методы в таблице методов класса
super
позволяет обратиться к родительской версииПри вызове метода Ruby проверяет:
Ruby не имеет встроенных абстрактных методов, но можно имитировать:
class AbstractParser
def parse
raise NotImplementedError, "Метод parse должен быть реализован в подклассе"
end
end
class JsonParser < AbstractParser
def parse
# Реальная реализация
end
end
Виртуальные методы часто используются в шаблонных методах:
class Report
def generate
prepare_data
format_report
save
end
def prepare_data
# Базовая реализация
end
def format_report
raise NotImplementedError
end
def save
# Базовая реализация
end
end
virtual
class String
def length
super / 2 # Опасное переопределение встроенного метода
end
end
Резюмируем: в Ruby все методы по умолчанию являются виртуальными, что обеспечивает гибкость и мощный полиморфизм. Это позволяет легко создавать сложные иерархии классов, где подклассы могут изменять и расширять поведение родительских классов. Понимание этой особенности критически важно для эффективного ООП в Ruby.