Использование многоуровневого наследования вместо ruby ​​mixins - PullRequest
5 голосов
/ 20 сентября 2019

Вот пример многоуровневого наследования в ruby, здесь у нас есть 3 класса A, B и C. B наследуется от A, а C наследуется от B, поэтому в конце класс C имеет все методы A, B и C..

class A
  def hello_by_a
    puts "A says hello"
  end
end

class B < A
  def hello_by_b
    puts "B says hello"
  end
end

class C < B
  def hello_by_c
    puts "C says hello"
  end
end

c = C.new
c.hello_by_a #=> A says hello
c.hello_by_b #=> B says hello
c.hello_by_c #=> C says hello

p c.methods-Object.methods #=> [:hello_by_c, :hello_by_b, :hello_by_a]

И здесь то же самое, что и миксины, здесь вместо классов A и B у нас есть модули A и B, которые включаются в класс C. Теперь класс C имеет все 3 метода

module A
  def hello_by_a
    puts "A says hello"
  end
end

module B
  def hello_by_b
    puts "B says hello"
  end
end

class C
  include A
  include B

  def hello_by_c
    puts "C says hello"
  end
end

c = C.new

c.hello_by_a #=> A says hello
c.hello_by_b #=> B says hello
c.hello_by_c #=> C says hello

p c.methods-Object.methods #=> [:hello_by_c, :hello_by_b, :hello_by_a]

В конце, если мы сделаем это обоими способами, класс C будет иметь все методы класса A и B или модуль A и B. Так почему же лучше использовать модули вместо многоуровневого наследования с классами?

Я знаю, что мы должны использовать миксины, но на самом деле не знаю, почему мы не должны использовать многоуровневое наследование, как описано выше.Каковы недостатки и преимущества.если есть?

1 Ответ

6 голосов
/ 20 сентября 2019

Две основные причины:

Вы можете наследовать только от одного класса, но вы можете смешивать столько миксинов, сколько захотите.Это означает, что наследование является чрезвычайно «дорогим» в том смысле, что если вы вынуждены использовать наследование, вы вынуждены «использовать» 100% своих «ресурсов наследования».

Вы можете создавать миксины любым способом.ты хочешь.В вашем примере я могу получить только методы A, методы AB и методы ABC.Я не могу, например, получить только методы B.С миксинами я могу составить их в любой комбинации: только A, только B, только C, AB, AC, BCABC.Я также могу составить их в любом порядке Я хочу: у меня могут быть методы C переопределить методы B или у меня могут быть методы B переопределить методы C.

Я легко могу представить себе объект, который является Enumerable и Comparable.(Например, String s Comparable и до Ruby 1.9, они также были Enumerable.) В вашем предлагаемом мире это было бы возможно, только еслиEnumerable наследуется от Comparable или Comparable наследуется от Enumerable.Однако это не будет работать: Numeric s Comparable, но не Enumerable, Array s Enumerable, но не Comparable.

Существует также более философская / семантическая причина: перечислимость и сопоставимость являются полностью ортогональными понятиями, почему будет связывать их так тесно?Наследование является одной из самых близких форм связи, которые мы имеем, связывая два понятия близко друг к другу, которые на самом деле не имеют ничего общего друг с другом, просто неправильно .

...