2016-06-13 16 views
1

Ich habe versucht, eine neue Variable/Objekt zu seiner Basisklasse zu werfen, aber wenn ich debuggen merke ich, dass es die Klassenmitglieder der abgeleiteten Klasse hat. Wenn ich also eine überladene Methode aufruft, ruft sie die abgeleitete Klasse anstelle der Basis auf, obwohl das Objekt als Basis deklariert ist.C# Casting auf die Basisklasse und die Verwendung der Methoden

Um dies zu beheben, muss ich die ToString() -Methode in der abgeleiteten Klasse als neu definieren. Aber ich verstehe nicht warum, weil ich in die Basis gieße, also sollte es die Basismethode verwenden? Liegt es an der Art und Weise, wie der Compiler Referenzobjekte behandelt? Das neue Objekt der Basisklasse verweist immer noch auf den abgeleiteten Klassenspeicher, anstatt die entsprechenden Daten in seinen eigenen Speicherblock zu kopieren.

+9

Seltsame Welt. Die Leute kennen die komplexe Syntax von Lambda-Ausdrücken, kennen aber die 3. Säule von OOP nicht. –

+0

Seltsame Welt. :) –

Antwort

3

Ja und das ist bekannt als Polymorphism oder Laufzeitpolymorphie. Es passiert so, weil der tatsächliche Typ Student ist, obwohl der deklarierte Typ person in Ihrer unteren Codezeile ist. Der Methodenaufruf erfolgt also auf dem tatsächlichen Typ und nicht auf dem deklarierten Typ.

Person person = new Student("Bill", 3.5, "chem"); 
3

Es sind drei Schlüsselwörter erforderlich, um dieses Verhalten mit Polymorphismus zu steuern. Virtuell, überschreiben und neu. Diese sind gut erklärt here und von MSDN:

Aufschalten:

Die Überschreibung Modifikator kann auf virtuellen Methoden verwendet werden und muss auf abstrakte Methoden verwendet werden. Dies zeigt an, dass der Compiler die letzte definierte Implementierung einer Methode verwendet. Selbst wenn die Methode für eine Referenz auf die Basisklasse aufgerufen wird, wird sie von der Implementierung überschrieben.

Neu:

Der neue Modifikator weist den Compiler Ihr Kind Klasse Implementierung anstelle der übergeordneten Klasse Implementierung zu verwenden. Jeder Code, der nicht auf Ihre Klasse, sondern auf die Elternklasse verweist, verwendet die Implementierung der Elternklasse.

Ein Beispiel:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace BindingExample 
{ 
    public class SomeBaseClass 
    { 
     public virtual string CustomString() => "From SomeBaseClass"; 
    } 

    public class FirstSpecialisation : SomeBaseClass 
    { 
     public override string CustomString() => "From FirstSpecialisation"; 
    } 

    public class SecondSpecialisation : SomeBaseClass 
    { 
     public new string CustomString() => "From SecondSpecialisation"; 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Base Example, as expected 
      SomeBaseClass a1 = new SomeBaseClass(); 

      Console.WriteLine(a1.CustomString()); 

      // First Example, both output the same result 
      FirstSpecialisation b1 = new FirstSpecialisation(); 
      SomeBaseClass b2 = b1; 

      Console.WriteLine(b1.CustomString()); 
      Console.WriteLine(b2.CustomString()); 

      // Second Example, output different results 
      SecondSpecialisation c1 = new SecondSpecialisation(); 
      SomeBaseClass c2 = c1; 

      Console.WriteLine(c1.CustomString()); 
      Console.WriteLine(c2.CustomString()); 

      Console.ReadLine(); 
     } 
    } 
} 

Ausgang:

From SomeBaseClass 
From FirstSpecialisation 
From FirstSpecialisation 
From SecondSpecialisation 
From SomeBaseClass 

Beachten Sie das obige Verhalten mit der SecondSpecialisation Klasse auf den Linien 4 und 5

Dies ist besonders interessant in Ihrem Beispiel ist , weil Sie eine Methode mit 2 Tiefen überschreiben. Wenn Sie zweimal überlagern, wird ein ungewöhnliches Verhalten hervorgerufen. Die letzte überschriebene Priorität hat Vorrang. Daher müssen Sie das neue Schlüsselwort verwenden.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace BindingExample 
{ 
    public class SomeBaseClassA 
    { 
     public override string ToString() => "From SomeBaseClassA"; 
    } 

    public class SpecialisationA : SomeBaseClassA 
    { 
     public override string ToString() => "From SpecialisationA"; 
    } 

    public class SomeBaseClassB 
    { 
     public new string ToString() => "From SomeBaseClassB"; 
    } 

    public class SpecialisationB : SomeBaseClassB 
    { 
     public new string ToString() => "From SpecialisationB"; 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      // First Example 
      SomeBaseClassA a1 = new SomeBaseClassA(); 
      Console.WriteLine(a1); 

      SpecialisationA a2 = new SpecialisationA(); 
      Console.WriteLine(a2); 

      SomeBaseClassA a3 = a2; 
      Console.WriteLine(a3); 

      // Second Example 
      SomeBaseClassB b1 = new SomeBaseClassB(); 
      Console.WriteLine(b1.ToString()); 

      SpecialisationB b2 = new SpecialisationB(); 
      Console.WriteLine(b2.ToString()); 

      SomeBaseClassB b3 = b2; 
      Console.WriteLine(b3.ToString()); 

      Console.ReadLine(); 
     } 
    } 
} 

Ausgang:

From SomeBaseClassA 
From SpecialisationA 
From SpecialisationA 
From SomeBaseClassB 
From SpecialisationB 
From SomeBaseClassB 

beobachte ich habe, wenn die ToString Methode überschrieben, die es auf Object genannt wurde. Ich nehme an, dies ist, weil die Methode ein Objekt nehmen kann, und weil das neue Schlüsselwort in den 'ToString' Methoden innerhalb der Spezialisierungen verwendet wurde, ruft der Compiler stattdessen Object.ToString. Dies ist etwas, auf das Sie achten sollten.

Verwandte Themen