Различие между новым и переопределением

Вид трудного вопроса для ответа... Я думаю, что все это зависит от Вашего приобретения знаний стиля.

я изучил LISP в своем A.I. и классы Экспертных систем в колледже, но это - то, как я учусь... Я не великий книжный ученик, я предпочитаю сделать, чтобы кто-то объяснил его мне в установке класса.

LISP является определенно уникальным языком, и он требует нового хода мыслей, если Вы привыкли к стандартному C, Java, программированию PHP.

Всего наилучшего Вам!

179
задан Mateen Ulhaq 7 January 2016 в 10:51
поделиться

6 ответов

Модификатор переопределения может использоваться на виртуальные методы и должны использоваться на абстрактные методы. Это указывает на компилятор использовать последний определенный реализация метода. Даже если метод вызывается по ссылке на базовый класс будет использовать

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public override void DoIt()
    {
    }
}

Base b = new Derived();
b.DoIt();                      // Calls Derived.DoIt

вызовет Derived.DoIt , если он переопределяет Base.DoIt .

Новый модификатор указывает компилятор для использования реализации вашего дочернего класса вместо родительского класса реализация. Любой код, который не ссылка на ваш класс, но родительский класс будет использовать родительский класс

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public new void DoIt()
    {
    }
}

Base b = new Derived();
Derived d = new Derived();

b.DoIt();                      // Calls Base.DoIt
d.DoIt();                      // Calls Derived.DoIt

Сначала вызовет Base.DoIt , затем Derived.DoIt . По сути, это два совершенно разных метода с одинаковыми именами, а не производный метод, заменяющий базовый метод.

Источник: Блог Microsoft

247
ответ дан 23 November 2019 в 06:15
поделиться

В случае 1, если вы использовали вызов метода DoIt () унаследованного класса, когда тип объявлен как базовый класс, вы увидите действие даже базового класса.

/* Results
Class1
Base1
Class2
Class2
*/
public abstract class Base1
{
    public void DoIt() { Console.WriteLine("Base1"); }
}
public  class Class1 : Base1 
{
    public new void DoIt() { Console.WriteLine("Class1"); }
}
public abstract class Base2
{
    public virtual void DoIt() { Console.WriteLine("Base2"); }
}
public class Class2 : Base2
{
    public override void DoIt() { Console.WriteLine("Class2"); }
}
static void Main(string[] args)
{
    var c1 = new Class1();
    c1.DoIt();
    ((Base1)c1).DoIt();

    var c2 = new Class2();
    c2.DoIt();
    ((Base2)c2).DoIt();
    Console.Read();
}
3
ответ дан 23 November 2019 в 06:15
поделиться

Разница между двумя случаями состоит в том, что в случае 1 метод base DoIt не переопределяется, а просто скрывается. Это означает, что от типа переменной зависит, какой метод будет вызван. Например:

BaseClass instance1 = new SubClass();
instance1.DoIt(); // Calls base class DoIt method

SubClass instance2 = new SubClass();
instance2.DoIt(); // Calls sub class DoIt method

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

просто спрятан. Это означает, что от типа переменной зависит, какой метод будет вызван. Например:

BaseClass instance1 = new SubClass();
instance1.DoIt(); // Calls base class DoIt method

SubClass instance2 = new SubClass();
instance2.DoIt(); // Calls sub class DoIt method

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

просто спрятан. Это означает, что в зависимости от типа переменной зависит, какой метод будет вызван. Например:

BaseClass instance1 = new SubClass();
instance1.DoIt(); // Calls base class DoIt method

SubClass instance2 = new SubClass();
instance2.DoIt(); // Calls sub class DoIt method

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

3
ответ дан 23 November 2019 в 06:15
поделиться

В первом случае вы скрываете определение в родительском классе. Это означает, что он будет вызываться только тогда, когда вы имеете дело с объектом как с дочерним классом. Если вы приведете класс к его родительскому типу, будет вызван родительский метод. Во втором случае метод переопределяется и будет вызываться независимо от того, приведен ли объект как дочерний или родительский класс.

15
ответ дан 23 November 2019 в 06:15
поделиться

попробуйте следующее: (case1)

((BaseClass)(new InheritedClass())).DoIt()

Изменить: виртуальное + переопределение разрешается во время выполнения (так что переопределение действительно переопределяет виртуальные методы), а new просто создает новый метод с тем же именем и скрывает старый, он разрешается во время компиляции -> ваш компилятор вызовет метод, который он «видит»

7
ответ дан 23 November 2019 в 06:15
поделиться

виртуальный : указывает, что метод может быть переопределен наследником.

переопределение : переопределяет функциональность виртуального метода в базовом классе, обеспечивая другую функциональность.

новый : скрывает исходный метод (который не обязательно должен быть виртуальным), обеспечивая другую функциональность. Это следует использовать только там, где это абсолютно необходимо.

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

168
ответ дан 23 November 2019 в 06:15
поделиться
Другие вопросы по тегам:

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