Почему использовать явную интерфейсную реализацию для вызова защищенного метода?

Проблема для вас в том, что в 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 - это наследование).

10
задан SW4 24 April 2014 в 08:09
поделиться

1 ответ

Ну, не характерный для 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() { ... }
}

Используя защищенный виртуальный подход, любое использование:

  • Нечто. Клон ()
  • Панель. Клон ()
  • ICloneable. Клон ()

все использование корректное CloneCore() реализация для конкретного типа.

14
ответ дан 3 December 2019 в 21:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: