Новое слово в интерфейсах в C #

голоса
3
using System;

namespace random

{

    interface IHelper
    {
        void HelpMeNow();
    }
    public class Base : IHelper
    {
        public void HelpMeNow()
        {
            Console.WriteLine(Base.HelpMeNow());
        }
    }
    public class Derived : Base
    {
        public new void HelpMeNow()            ///this line
        {
            Console.WriteLine(Derived.HelpMeNow());
        }
    }
    class Test
    {
        public static void Main()
        {
            Derived der = new Derived();
            der.HelpMeNow();
            IHelper helper = (IHelper)der;
            helper.HelpMeNow();
            Console.ReadLine();
        }
    }
}

новое ключевое слово в строке комментировал немного запутанным для меня. Это означает, что этого нужно просто переопределяет реализацию метода в базовом классе. Почему бы не использовать переопределение ключевое слово?

Задан 27/08/2009 в 01:01
источник пользователем
На других языках...                            


3 ответов

голоса
9

Смотрите эту статью на MSDN: знать , когда использовать Override и новые ключевые слова

Ответил 27/08/2009 в 01:03
источник пользователем

голоса
0

В общем, если интерфейс IBase реализует элемент DoSomething и IDerived наследует / реализует IBase, то ожидается, что IDerived.DoSomething будет синонимом IBase.DoSomething. В общем, это полезно, так как он сохраняет исполнитель класса от необходимости создания избыточных реализаций. Есть, однако, некоторые случаи, когда производный интерфейс должен реализовать элемент, который имеет такое же имя, как член в базовом интерфейсе, но который должен будет осуществляться отдельно. Наиболее распространенные такие ситуации (1), полученный метод будет иметь другой тип возвращаемого от базового типа, или (2) базовый интерфейс (ы) реализует свойство ReadOnly и / или WriteOnly (ы) с определенным и производным тип должен осуществлять чтение и запись свойств. По какой-то причине, если интерфейс IReadableFoo предоставляет свойство только для чтения Foo, IWritableFoo обеспечивает свойства только для записи Foo, и интерфейс IMutableFoo просто наследует как, компилятор не будет знать, относится ли ссылка на Foo, чтобы IReadableFoo.Foo или IWritableFoo.Foo. Даже если только IReadableFoo.Foo можно читать, и только IWritableFoo.Foo могут быть записаны, ни vb.net, ни C # может устранить перегрузку, если один не реализует новый для чтения и записи свойства Foo, который обрабатывает оба.

Ответил 24/07/2011 в 20:42
источник пользователем

голоса
0

Это на самом деле не перекрывая его, это слежка его. Учитывая это ссылка на Derivedобъект, Base«s HelpMeNowфункция не будет доступна 1 , и derivedObject.HelpMeNow()будет называть Derived» s выполнением.

Это не то же самое переопределение виртуальной функции, которая HelpMeNowне является. Если Derivedобъект хранится в ссылке к Baseили к IHelper, то Base«s HelpMeNow()будет называться, и Derived» s реализация будет недоступна.

Derived derivedReference = new Derived();
Base    baseReference    = derivedReference;
IHelper helperReference  = derivedReference;

derivedReference.HelpMeNow(); // outputs "Derived.HelpMeNow()"
baseReference.HelpMeNow();    // outputs "Base.HelpMeNow()"
helperReference.HelpMeNow();  // outputs "Base.HelpMeNow()"

Конечно, если выше не желаемое поведение, и это, как правило , нет, есть две возможности. Если вы контролируете Base, просто изменить HelpMeNow()к виртуальному, и переопределить его Derivedвместо затенения его. Если вы не контролируете Base, то вы можете , по крайней мере зафиксировать его на полпути, переопределение IHelper, например , так:

class Derived : Base, IHelper{
    public new void HelpMeNow(){Console.WriteLine("Derived.HelpMeNow()");}

    void IHelper.HelpMeNow(){HelpMeNow();}
}

Эта версия Derivedиспользует то , что называется явной реализацией интерфейса , который позволяет удовлетворить контракт , реализующий интерфейс без добавления реализации в открытом интерфейс вашего класса. В этом примере, мы уже имеем реализацию в Derived«s открытый интерфейс , который унаследовал от Base, так что мы должны явно реализовать , IHelperчтобы изменить его 2 . В этом примере мы только вперед реализацию IHelper.HelpMeNowнашего общего интерфейса, который является тенью Base«с.

Так что с этим изменением, вызов по- baseReference.HelpMeNow()прежнему выводит «Base.HelpMeNow ()», но вызов helperReference.HelpMeNow()теперь будет выход «Derived.HelpMeNow ()». Не так хорошо , как изменение Baseреализации «s к виртуальной, но так же хорошо , как мы собираемся получить , если мы не контролируем Base.

1 Исключение: она является доступна из методов Derived, но только тогда , когда квалифицирована base., как и в base.HelpMeNow().
2 Обратите внимание , что мы также должны объявить в IHelperкачестве интерфейса орудия класса, даже если мы наследуем эту декларацию от Base.

Ответил 27/08/2009 в 01:33
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more