Frage

    

Diese Frage bereits eine Antwort hier:

         

Ich bin ein wenig verwirrt über zwingende gegen ein Verfahren in C # zu verstecken. Praktische Anwendungen von jedem würden auch geschätzt werden, sowie eine Erklärung für , wenn würde man jede verwenden.

Ich bin verwirrt über zwingende - warum außer Kraft setzen wir? Was ich bisher gelernt habe, ist, dass durch overring wir gewünschte Umsetzung ein Verfahren zur Herstellung einer abgeleiteten Klasse zur Verfügung stellen kann, ohne die Signatur zu ändern.

Wenn ich die Methode der übergeordneten Klasse nicht außer Kraft setzen und ich Änderungen an die Methode in der Unterklasse, wird feststellen, dass Änderungen an die Super-Klasse-Methode?

Ich bin auch über die folgenden verwirrt - was bedeutet das zeigen

class A
{
    virtual m1()
    {
        console.writeline("Bye to all");
    }
}

class B : A
{
    override m1()
    {
        console.writeLine("Hi to all");
    }
}

class C
{
    A a = new A();
    B b = new B();
    a = b; (what is this)
    a.m1(); // what this will print and why?

    b = a; // what happens here?
}
War es hilfreich?

Lösung

Bedenken Sie:

public class BaseClass
{
  public void WriteNum()
  {
    Console.WriteLine(12);
  }
  public virtual void WriteStr()
  {
    Console.WriteLine("abc");
  }
}

public class DerivedClass : BaseClass
{
  public new void WriteNum()
  {
    Console.WriteLine(42);
  }
  public override void WriteStr()
  {
    Console.WriteLine("xyz");
  }
}
/* ... */
BaseClass isReallyBase = new BaseClass();
BaseClass isReallyDerived = new DerivedClass();
DerivedClass isClearlyDerived = new DerivedClass();

isReallyBase.WriteNum(); // writes 12
isReallyBase.WriteStr(); // writes abc
isReallyDerived.WriteNum(); // writes 12
isReallyDerived.WriteStr(); // writes xyz
isClearlyDerived.WriteNum(); // writes 42
isClearlyDerived.writeStr(); // writes xyz

Übergeordnete sind die klassische OO Weise, in der eine abgeleitete Klasse spezifischere Verhalten als eine Basisklasse haben kann (in einigen Sprachen haben Sie keine andere Wahl, dies zu tun). Wenn eine virtuelle Methode für ein Objekt aufgerufen wird, dann wird die abgeleitete Version des Verfahrens genannt. Daher, auch wenn wir mit isReallyDerived als BaseClass dann Funktionalität definiert in DerivedClass handeln verwendet wird.

Hiding bedeutet, dass wir eine ganz andere Methode haben. Wenn wir WriteNum() auf isReallyDerived rufen dann gibt es keine Möglichkeit zu wissen, dass es eine andere WriteNum() auf DerivedClass ist, damit es nicht aufgerufen wird. Es kann nur aufgerufen werden, wenn wir mit dem Objekt wie ein DerivedClass.

handeln

Die meiste Zeit versteckt ist schlecht. Im Allgemeinen wird entweder sollten Sie eine Methode als virtuelle, wenn seine wahrscheinlich in einer abgeleiteten Klasse geändert werden, und es in der abgeleiteten Klasse überschreiben. Es gibt jedoch zwei Dinge, die es ist nützlich für:

  1. Vorwärts-Kompatibilität. Wenn DerivedClass eine DoStuff() Methode hatte, und dann später auf BaseClass geändert wurde eine DoStuff() Methode hinzufügen, (denken Sie daran, dass sie von verschiedenen Leuten geschrieben werden können, und gibt es in verschiedenen Baugruppen), dann wäre ein Verbot Mitglied Versteck plötzlich DerivedClass Buggy ohne sie gemacht haben Ändern. Auch wenn der neue DoStuff() auf BaseClass virtuelle war, dann automatisch zu machen, dass auf DerivedClass eine Überschreibung davon die bereits bestehende Methode aufgerufen führen könnte, das, wenn es nicht sollte. Daher ist es gut, dass versteckt ist der Standard (wir new verwenden, um es uns auf jeden Fall zu verstecken wollen deutlich machen, aber es aus Häuten und gibt eine Warnung auf Kompilation zu verlassen).

  2. Arme-Leute-Kovarianz. Betrachten wir ein Clone() Methode auf BaseClass, die eine neue BaseClass zurückgibt, die eine Kopie davon erstellt ist. In der Überschreibung auf DerivedClass wird dies eine DerivedClass schaffen, sondern bringen Sie es als BaseClass, die nicht so nützlich ist. Was wir tun können, ist eine virtuelle geschützten CreateClone() zu haben, die außer Kraft gesetzt wird. In BaseClass haben wir eine Clone(), dass die Renditen das Ergebnis dieser - und alles ist gut - in DerivedClass wir verstecken dies mit einem neuen Clone(), die eine DerivedClass zurückgibt. Der Aufruf Clone() auf BaseClass wird immer eine BaseClass Referenz zurückgeben, die ein BaseClass Wert oder ein DerivedClass Wert als angemessen sein wird. Clone() auf DerivedClass Aufruf wird ein DerivedClass Wert zurückgeben, was ist das, was wir in diesem Zusammenhang wollen würde. Es gibt auch andere Varianten dieses Prinzip jedoch ist zu beachten, dass sie alle ziemlich selten sind.

Eine wichtige Sache zu beachten mit dem zweiten Fall, ist, dass wir Versteck genau verwendet haben Entfernen überrascht auf die Telefonvorwahl, wie die Person DerivedClass mit vernünftigerweise erwarten, dass seinem Clone() ein DerivedClass zurückzukehren . Die Ergebnisse einer der Wege könnte sie gehalten werden miteinander konsistent bezeichnet werden. Die meisten Fälle von verstecken Risiko Überraschungen Einführung, weshalb sie auf allgemein verpönt sind. Dieser ist gerechtfertigt, gerade weil es das sehr Problem löst, dass versteckt häufig vor.

Insgesamt Versteck ist manchmal notwendig, selten nützlich, aber in der Regel schlecht, so sehr vorsichtig sein es.

Andere Tipps

Overriding is when you provide a new override implementation of a method in a descendant class when that method is defined in the base class as virtual.

Hiding is when you provide a new implementation of a method in a descendant class when that method is not defined in the base class as virtual, or when your new implementation does not specify override.

Hiding is very often bad; you should generally try not to do it if you can avoid it at all. Hiding can cause unexpected things to happen, because Hidden methods are only used when called on a variable of the actual type you defined, not if using a base class reference... on the other hand, Virtual methods which are overridden will end up with the proper method version being called, even when called using the base class reference on a child class.

For instance, consider these classes:

public class BaseClass
{
  public virtual void Method1()  //Virtual method
  {
    Console.WriteLine("Running BaseClass Method1");
  }
  public void Method2()  //Not a virtual method
  {
    Console.WriteLine("Running BaseClass Method2");
  }
}
public class InheritedClass : BaseClass
{
  public override void Method1()  //Overriding the base virtual method.
  {
    Console.WriteLine("Running InheritedClass Method1");
  }
  public new void Method2()  //Can't override the base method; must 'new' it.
  {
    Console.WriteLine("Running InheritedClass Method2");
  }
}

Let's call it like this, with an instance of InheritedClass, in a matching reference:

InheritedClass inherited = new InheritedClass();
inherited.Method1();
inherited.Method2();

This returns what you should expect; both methods say they are running the InheritedClass versions.

Running InheritedClass Method1
Running InheritedClass Method2

This code creates an instance of the same, InheritedClass, but stores it in a BaseClass reference:

BaseClass baseRef = new InheritedClass();
baseRef.Method1();
baseRef.Method2();

Normally, under OOP principles, you should expect the same output as the above example. But you don't get the same output:

Running InheritedClass Method1
Running BaseClass Method2

When you wrote the InheritedClass code, you may have wanted all calls to Method2() to run the code you wrote in it. Normally, this would be how it works - assuming you are working with a virtual method that you have overridden. But because you are using a new/hidden method, it calls the version on the reference you are using, instead.


If that's the behavior you truly want, then; there you go. But I would strongly suggest that if that's what you want, there may be a larger architectural issue with the code.

Method Overriding is simpley override a default implementation of a base class method in the derived class.

Method Hiding : You can make use of 'new' keyword before a virtual method in a derived class

as

class Foo  
{  
  public virtual void foo1()  
  {  

  }  
}  

class Bar:Foo  
{  
  public new virtual void foo1()  
  {   

  }  
}  

now if you make another class Bar1 which is derived from Bar , you can override foo1 which is defind in Bar.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top