Цепочка наследования с переопределением и затенением [дубликат]

Существует метод для итерации только собственных свойств объекта, не считая его прототипов:

for (var i in array) if (array.hasOwnProperty(i)) {
    // do something with array[i]
}

, но он все равно будет перебирать настраиваемые свойства.

В javascript any пользовательское свойство может быть назначено любому объекту, включая массив.

Если требуется итерация по разреженному массиву, следует использовать for (var i = 0; i < array.length; i++) if (i in array) или array.forEach с es5shim.

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

13 ответов

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

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

196
ответ дан bluish 29 August 2018 в 01:23
поделиться

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

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

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

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

3
ответ дан Christian Specht 29 August 2018 в 01:23
поделиться

В первом случае он вызовет метод DoIt () производного класса, потому что новое ключевое слово скрывает метод базового класса DoIt ().

Во втором случае он вызовет overriden DoIt ()

  public class A
{
    public virtual void DoIt()
    {
        Console.WriteLine("A::DoIt()");
    }
}

public class B : A
{
    new public void DoIt()
    {
        Console.WriteLine("B::DoIt()");
    }
}

public class C : A
{
    public override void DoIt()
    {
        Console.WriteLine("C::DoIt()");
    }
}

позволяет создать экземпляр этих классов

   A instanceA = new A();

    B instanceB = new B();
    C instanceC = new C();

    instanceA.DoIt(); //A::DoIt()
    instanceB.DoIt(); //B::DoIt()
    instanceC.DoIt(); //B::DoIt()

Все ожидается выше. Позвольте задать экземпляр B и instanceC в instanceA и вызвать метод DoIt () и проверить результат.

    instanceA = instanceB;
    instanceA.DoIt(); //A::DoIt() calls DoIt method in class A

    instanceA = instanceC;
    instanceA.DoIt();//C::DoIt() calls DoIt method in class C because it was overriden in class C
0
ответ дан cimey 29 August 2018 в 01:23
поделиться

Функциональная разница не будет отображаться в этих тестах:

BaseClass bc = new BaseClass();

bc.DoIt();

DerivedClass dc = new DerivedClass();

dc.ShowIt();

В этом примере, вызванная Doit является той, которую вы ожидаете назвать.

In чтобы увидеть разницу, которую вы должны сделать:

BaseClass obj = new DerivedClass();

obj.DoIt();

Вы увидите, если вы запустите этот тест, который в случае 1 (как вы его определили), DoIt() в BaseClass (в том случае, если вы определили его), вызывается DoIt() в DerivedClass.

0
ответ дан Ken Falk 29 August 2018 в 01:23
поделиться

В случае 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
ответ дан Matthew Whited 29 August 2018 в 01:23
поделиться

попробуйте выполнить: (case1)

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

Edit: virtual + override разрешены во время выполнения (поэтому переопределение действительно отменяет виртуальные методы), а новые просто создают новый метод с тем же именем и скрывает старый, он разрешен во время компиляции -> ваш компилятор вызовет метод, который он видит '

7
ответ дан nothrow 29 August 2018 в 01:23
поделиться

Ниже приведена статья в vb.net, но я думаю, что объяснение новых переопределений vs очень легко понять.

https://www.codeproject.com/articles/17477/ the-dark-shadow of of-overrides

В какой-то момент статьи есть следующее предложение:

В общем, Shadows предполагает связанную с этим функцию с вызовом type, в то время как Overrides предполагает реализацию объекта.

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

1
ответ дан Samuel 29 August 2018 в 01:23
поделиться

Если в производном классе используется ключевое слово override, то оно переопределяет родительский метод.

Если ключевое слово new используется в производном классе, то выведите метод, скрытый родительским методом.

1
ответ дан Sangram Nandkhile 29 August 2018 в 01:23
поделиться

Мой способ иметь в виду оба ключевых слова, которые они противоположны друг другу.

override: ключевое слово virtual должно быть определено для переопределения метода. Метод, использующий ключевое слово override, независимо от ссылочного типа (ссылка на базовый класс или производный класс), если он создается с базовым классом, выполняется метод базового класса. В противном случае используется метод производного класса.

new: если ключевое слово используется методом, в отличие от ключевого слова override, тип ссылки важен. Если он создается с производным классом, а ссылочный тип - это базовый класс, выполняется метод базового класса. Если он создается с производным классом, а ссылочный тип - это производный класс, выполняется метод производного класса. А именно, это отличие от ключевого слова override. En passant, если вы забыли или опустите, чтобы добавить новое ключевое слово в метод, компилятор ведет себя по умолчанию при использовании ключевого слова new.

class A 
{
    public string Foo() 
    {
        return "A";
    }

    public virtual string Test()
    {
        return "base test";
    }
}

class B: A
{
    public new string Foo() 
    {
        return "B";
    }
}

class C: B 
{
    public string Foo() 
    {
        return "C";
    }

    public override string Test() {
        return "derived test";
    }
}

Вызов в основном:

A AClass = new B();
Console.WriteLine(AClass.Foo());
B BClass = new B();
Console.WriteLine(BClass.Foo());
B BClassWithC = new C();
Console.WriteLine(BClassWithC.Foo());

Console.WriteLine(AClass.Test());
Console.WriteLine(BClassWithC.Test());

Выход:

A
B
B
base test
derived test
2
ответ дан snr 29 August 2018 в 01:23
поделиться

virtual: указывает, что метод может быть переопределен переопределением функции inheritor

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

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

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

155
ответ дан Sнаđошƒаӽ 29 August 2018 в 01:23
поделиться

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

14
ответ дан tvanfosson 29 August 2018 в 01:23
поделиться

Из всего этого новое - самое запутанное. Благодаря экспериментированию новое ключевое слово похоже на предоставление разработчикам возможности переопределить реализацию наследующего класса с реализацией базового класса, явно определяя тип. Это похоже на то, как думать наоборот.

В приведенном ниже примере результат вернет «Производный результат» до тех пор, пока тип явно не будет определен как тест BaseClass, только тогда будет возвращен «Базовый результат».

class Program
{
    static void Main(string[] args)
    {
        var test = new DerivedClass();
        var result = test.DoSomething();
    }
}

class BaseClass
{
    public virtual string DoSomething()
    {
        return "Base result";
    }
}

class DerivedClass : BaseClass
{
    public new string DoSomething()
    {
        return "Derived result";
    }
}
1
ответ дан usefulBee 29 August 2018 в 01:23
поделиться

У меня был тот же вопрос, и это действительно запутанно, вы должны учитывать, что переопределение и новые ключевые слова работают только с объектами базового класса типа и значением производного класса. В этом случае вы увидите эффект переопределения и новый: Итак, если у вас есть class A и B, B наследуется от A, вы создаете экземпляр объекта следующим образом:

A a = new B();

Теперь при вызове методы учитывают его состояние. Override: означает, что он расширяет функцию метода, а затем использует метод в производном классе, тогда как новый сообщает компилятору, чтобы скрыть метод в производном классе и вместо этого использовать метод в базовом классе. Вот очень хороший взгляд на эту тему:

https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2% 29.aspx е = 255 & амп;? MSPPError = -2147217396

0
ответ дан user 29 August 2018 в 01:23
поделиться
Другие вопросы по тегам:

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