Проблема для вас в том, что в Ruby нет множественного наследования; поэтому модули вставляются как предки один над другим и как таковые F#initialize
омрачают E#initialize
. Как вы обнаружили, к нему легко получить доступ F#initialize
, используя super(f)
; но другому нужен взлом для доступа: мы можем выбрать метод initialize
непосредственно из модуля, потому что он является предком; затем привязать его к текущему объекту и запустить его.
def initialize(e, f)
E.instance_method(:initialize).bind(self).call(e)
F.instance_method(:initialize).bind(self).call(f) # equivalent to super(f)
end
Однако я не рекомендую это. Если вам нужно запустить несколько инициализаторов, вам лучше использовать композицию, а не наследование (и, надо понимать, include
- это наследование).
Ну, не характерный для MVC, но этого подхода позволяет Вам содержать базовый общедоступный API в чистоте. Также полезно, если существует когда-нибудь риск различных интерфейсов / и т.д. наличие того же имени и подписи, но другого значения. В действительности это редко.
Это также позволяет Вам обеспечивать реализацию, где Вы хотите, чтобы тип возврата изменился в подклассах:
(ICloneable
выбранный для простоты - не становятся одержимыми тем, что это - плохо определенный интерфейс... лучшим примером были бы вещи как DbCommand
и т.д., которые делают это - но это более трудно показать в коротком примере),
class Foo : ICloneable
{
public Foo Clone() { return CloneCore(); }
object ICloneable.Clone() { return CloneCore(); }
protected virtual Foo CloneCore() { ... }
}
class Bar : Foo
{
protected override Foo CloneCore() { ... }
public new Bar Clone() { return (Bar)CloneCore(); }
}
Если бы мы использовали общедоступный виртуальный метод, мы не смогли бы override
это и использование new
в базовом классе, поскольку Нельзя сделать обоих:
class A
{
public virtual A SomeMethod() { ... }
}
class B : A
{
public override A SomeMethod() { ... }
//Error 1 Type 'B' already defines a member called 'SomeMethod' with the same parameter types
public new B SomeMethod() { ... }
}
Используя защищенный виртуальный подход, любое использование:
все использование корректное CloneCore()
реализация для конкретного типа.