Вид трудного вопроса для ответа... Я думаю, что все это зависит от Вашего приобретения знаний стиля.
я изучил LISP в своем A.I. и классы Экспертных систем в колледже, но это - то, как я учусь... Я не великий книжный ученик, я предпочитаю сделать, чтобы кто-то объяснил его мне в установке класса.
LISP является определенно уникальным языком, и он требует нового хода мыслей, если Вы привыкли к стандартному C, Java, программированию PHP.
Всего наилучшего Вам!
Модификатор переопределения может использоваться на виртуальные методы и должны использоваться на абстрактные методы. Это указывает на компилятор использовать последний определенный реализация метода. Даже если метод вызывается по ссылке на базовый класс будет использовать
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
В случае 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();
}
Разница между двумя случаями состоит в том, что в случае 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.
В первом случае вы скрываете определение в родительском классе. Это означает, что он будет вызываться только тогда, когда вы имеете дело с объектом как с дочерним классом. Если вы приведете класс к его родительскому типу, будет вызван родительский метод. Во втором случае метод переопределяется и будет вызываться независимо от того, приведен ли объект как дочерний или родительский класс.
попробуйте следующее: (case1)
((BaseClass)(new InheritedClass())).DoIt()
Изменить: виртуальное + переопределение разрешается во время выполнения (так что переопределение действительно переопределяет виртуальные методы), а new просто создает новый метод с тем же именем и скрывает старый, он разрешается во время компиляции -> ваш компилятор вызовет метод, который он «видит»
виртуальный : указывает, что метод может быть переопределен наследником.
переопределение : переопределяет функциональность виртуального метода в базовом классе, обеспечивая другую функциональность.
новый : скрывает исходный метод (который не обязательно должен быть виртуальным), обеспечивая другую функциональность. Это следует использовать только там, где это абсолютно необходимо.
Когда вы скрываете метод, вы все равно можете получить доступ к исходному методу путем преобразования вверх к базовому классу. Это полезно в некоторых сценариях, но опасно.