Ruby Language
наследование
Поиск…
Синтаксис
- класс SubClass <SuperClass
Рефакторинг существующих классов для использования Наследование
Предположим, у нас есть два класса: Cat
и Dog
.
class Cat
def eat
die unless has_food?
self.food_amount -= 1
self.hungry = false
end
def sound
puts "Meow"
end
end
class Dog
def eat
die unless has_food?
self.food_amount -= 1
self.hungry = false
end
def sound
puts "Woof"
end
end
Метод eat
точно такой же в этих двух классах. Хотя это работает, его трудно поддерживать. Проблема будет ухудшаться, если есть больше животных с тем же методом eat
. Наследование может решить эту проблему.
class Animal
def eat
die unless has_food?
self.food_amount -= 1
self.hungry = false
end
# No sound method
end
class Cat < Animal
def sound
puts "Meow"
end
end
class Dog < Animal
def sound
puts "Woof"
end
end
Мы создали новый класс, Animal
, и перевели наш метод eat
в этот класс. Затем мы заставили Cat
и Dog
наследовать этот новый общий суперкласс. Это устраняет необходимость повторения кода
Многократное наследование
Множественное наследование - это функция, позволяющая одному классу наследовать от нескольких классов (т. Е. Более одного родителя). Ruby не поддерживает множественное наследование. Он поддерживает только однонаследование (т.е. класс может иметь только один родительский элемент), но вы можете использовать композицию для построения более сложных классов с использованием модулей .
Подклассы
Наследование позволяет классам определять конкретное поведение на основе существующего класса.
class Animal
def say_hello
'Meep!'
end
def eat
'Yumm!'
end
end
class Dog < Animal
def say_hello
'Woof!'
end
end
spot = Dog.new
spot.say_hello # 'Woof!'
spot.eat # 'Yumm!'
В этом примере:
-
Dog
наследует отAnimal
, делая ее подклассом . -
Dog
получает какsay_hello
иeat
методы отAnimal
. -
Dog
переопределяет методsay_hello
с разной функциональностью.
Примеси
Mixins - прекрасный способ добиться чего-то подобного множественному наследованию. Это позволяет нам наследовать или, скорее, включать методы, определенные в модуле в класс. Эти методы могут быть включены как методы экземпляра или класса. В приведенном ниже примере изображена эта конструкция.
module SampleModule
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def method_static
puts "This is a static method"
end
end
def insta_method
puts "This is an instance method"
end
end
class SampleClass
include SampleModule
end
sc = SampleClass.new
sc.insta_method
prints "This is an instance method"
sc.class.method_static
prints "This is a static method"
Что унаследовано?
Методы наследуются
class A
def boo; p 'boo' end
end
class B < A; end
b = B.new
b.boo # => 'boo'
Методы класса унаследованы
class A
def self.boo; p 'boo' end
end
class B < A; end
p B.boo # => 'boo'
Константы унаследованы
class A
WOO = 1
end
class B < A; end
p B::WOO # => 1
Но будьте осторожны, их можно переопределить:
class B
WOO = WOO + 1
end
p B::WOO # => 2
Переменные экземпляра наследуются:
class A
attr_accessor :ho
def initialize
@ho = 'haha'
end
end
class B < A; end
b = B.new
p b.ho # => 'haha'
Опасайтесь, если вы переопределите методы, которые инициализируют переменные экземпляра без вызова super
, они будут равны нулю. Продолжая сверху:
class C < A
def initialize; end
end
c = C.new
p c.ho # => nil
Переменные экземпляра класса не наследуются:
class A
@foo = 'foo'
class << self
attr_accessor :foo
end
end
class B < A; end
p B.foo # => nil
# The accessor is inherited, since it is a class method
#
B.foo = 'fob' # possible
Переменные класса на самом деле не унаследованы
Они распределяются между базовым классом и всеми подклассами как 1 переменная:
class A
@@foo = 0
def initialize
@@foo += 1
p @@foo
end
end
class B < A;end
a = A.new # => 1
b = B.new # => 2
Итак, продолжая сверху:
class C < A
def initialize
@@foo = -10
p @@foo
end
end
a = C.new # => -10
b = B.new # => -9