Geçersiz Kılmanın ve Yeni Anahtar Sözcüklerin Ne Zaman Kullanılacağını Bilme (C# Programlama Kılavuzu)

C# dilinde, türetilmiş bir sınıftaki bir yöntem, temel sınıftaki bir yöntemle aynı ada sahip olabilir. Yöntemlerin yeni ve geçersiz kılma anahtar sözcüklerini kullanarak nasıl etkileşim kuracağını belirtebilirsiniz. Değiştirici, temel sınıf virtual yöntemini genişletir ve new değiştirici erişilebilir bir temel sınıf yöntemini gizler.override Fark, bu konudaki örneklerde gösterilmiştir.

Konsol uygulamasında aşağıdaki iki sınıfı BaseClass ve DerivedClassbildirin. DerivedClass öğesinden BaseClassdevralır.

class BaseClass  
{  
    public void Method1()  
    {  
        Console.WriteLine("Base - Method1");  
    }  
}  
  
class DerivedClass : BaseClass  
{  
    public void Method2()  
    {  
        Console.WriteLine("Derived - Method2");  
    }  
}  

yönteminde Main , dcve bcdcdeğişkenlerini bcbildirin.

  • bc türündedir BaseClassve değeri türündedir BaseClass.

  • dc türündedir DerivedClassve değeri türündedir DerivedClass.

  • bcdc türündedir BaseClassve değeri türündedir DerivedClass. Bu, dikkate alınacak değişkendir.

ve bcbcdc türüne BaseClasssahip olduğundan, atama kullanmadığınız sürece yalnızca doğrudan erişebilirler Method1. Değişken dc hem hem de Method1Method2öğesine erişebilir. Bu ilişkiler aşağıdaki kodda gösterilmiştir.

class Program  
{  
    static void Main(string[] args)  
    {  
        BaseClass bc = new BaseClass();  
        DerivedClass dc = new DerivedClass();  
        BaseClass bcdc = new DerivedClass();  
  
        bc.Method1();  
        dc.Method1();  
        dc.Method2();  
        bcdc.Method1();  
    }  
    // Output:  
    // Base - Method1  
    // Base - Method1  
    // Derived - Method2  
    // Base - Method1  
}  

Ardından, aşağıdaki Method2 yöntemi öğesine BaseClassekleyin. Bu yöntemin imzası içindeki DerivedClassyöntemin imzası ile Method2 eşleşir.

public void Method2()  
{  
    Console.WriteLine("Base - Method2");  
}  

Artık bir yöntemi olduğundanBaseClass, aşağıdaki kodda gösterildiği gibi ve bcdcdeğişkenleri bc için BaseClass ikinci bir çağırma deyimi Method2 eklenebilir.

bc.Method1();  
bc.Method2();  
dc.Method1();  
dc.Method2();  
bcdc.Method1();  
bcdc.Method2();  

Projeyi oluştururken yönteminin eklenmesinin bir uyarıya Method2BaseClass neden olduğunu görürsünüz. Uyarı, içindeki yönteminin Method2 içindeki BaseClassyöntemini gizlediğini Method2 söyler.DerivedClass Bu sonuda neden olmak istiyorsanız tanımda Method2 anahtar sözcüğünü kullanmanız new tavsiye edilir. Alternatif olarak, uyarıyı Method2 çözümlemek için yöntemlerden birini yeniden adlandırabilirsiniz, ancak bu her zaman pratik değildir.

eklemeden newönce, ek çağrı deyimleri tarafından üretilen çıkışı görmek için programı çalıştırın. Aşağıdaki sonuçlar görüntülenir.

// Output:  
// Base - Method1  
// Base - Method2  
// Base - Method1  
// Derived - Method2  
// Base - Method1  
// Base - Method2  

new anahtar sözcüğü, bu çıkışı oluşturan ilişkileri korur, ancak uyarıyı gizler. Türü BaseClass olan değişkenler, üyelerine BaseClasserişmeye devam eder ve türü DerivedClass olan değişken ilk olarak üyelere DerivedClass erişmeye ve ardından öğesinden BaseClassdevralınan üyeleri dikkate almaya devam eder.

Uyarıyı engellemek için, değiştiriciyi new aşağıdaki kodda DerivedClassgösterildiği gibi içindeki tanımına Method2 ekleyin. Değiştirici, öncesinde veya sonrasında publiceklenebilir.

public new void Method2()  
{  
    Console.WriteLine("Derived - Method2");  
}  

Çıkışın değişmediğini doğrulamak için programı yeniden çalıştırın. Ayrıca uyarının artık görünmediğini doğrulayın. kullanarak new, değiştirdiği üyenin temel sınıftan devralınan bir üyeyi gizlediğinin farkında olduğunuzu onaylarsınız. Devralma yoluyla ad gizleme hakkında daha fazla bilgi için bkz . yeni Değiştirici.

Bu davranışı kullanmanın overrideetkilerine karşıtlık sağlamak için, öğesine aşağıdaki yöntemi DerivedClassekleyin. Değiştirici, override öncesinde veya sonrasında publiceklenebilir.

public override void Method1()  
{  
    Console.WriteLine("Derived - Method1");  
}  

değiştiricisini virtual içindeki tanımına Method1BaseClassekleyin. Değiştirici, virtual öncesinde veya sonrasında publiceklenebilir.

public virtual void Method1()  
{  
    Console.WriteLine("Base - Method1");  
}  

Projeyi tekrar çalıştırın. Özellikle aşağıdaki çıkışın son iki satırına dikkat edin.

// Output:  
// Base - Method1  
// Base - Method2  
// Derived - Method1  
// Derived - Method2  
// Derived - Method1  
// Base - Method2  

Değiştiricinin override kullanılması, içinde DerivedClasstanımlanan yönteme Method1 erişmenizi sağlarbcdc. Genellikle, devralma hiyerarşilerinde istenen davranış budur. Türetilmiş sınıftan oluşturulan değerlere sahip nesnelerin türetilmiş sınıfta tanımlanan yöntemleri kullanmasını istiyorsunuz. Temel sınıf yöntemini genişletmek için kullanarak override bu davranışı elde edebilirsiniz.

Aşağıdaki kod, tam örneği içerir.

using System;  
using System.Text;  
  
namespace OverrideAndNew  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            BaseClass bc = new BaseClass();  
            DerivedClass dc = new DerivedClass();  
            BaseClass bcdc = new DerivedClass();  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in BaseClass.  
            bc.Method1();  
            bc.Method2();  
            // Output:  
            // Base - Method1  
            // Base - Method2  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in DerivedClass.  
            dc.Method1();  
            dc.Method2();  
            // Output:  
            // Derived - Method1  
            // Derived - Method2  
  
            // The following two calls produce different results, depending
            // on whether override (Method1) or new (Method2) is used.  
            bcdc.Method1();  
            bcdc.Method2();  
            // Output:  
            // Derived - Method1  
            // Base - Method2  
        }  
    }  
  
    class BaseClass  
    {  
        public virtual void Method1()  
        {  
            Console.WriteLine("Base - Method1");  
        }  
  
        public virtual void Method2()  
        {  
            Console.WriteLine("Base - Method2");  
        }  
    }  
  
    class DerivedClass : BaseClass  
    {  
        public override void Method1()  
        {  
            Console.WriteLine("Derived - Method1");  
        }  
  
        public new void Method2()  
        {  
            Console.WriteLine("Derived - Method2");  
        }  
    }  
}  

Aşağıdaki örnekte farklı bir bağlamda benzer davranışlar gösterilmektedir. Örnek üç sınıf tanımlar: adlı Car bir temel sınıf ve ondan ConvertibleCar türetilen iki sınıf ve Minivan. Temel sınıf bir DescribeCar yöntem içerir. yöntemi, bir arabanın temel açıklamasını görüntüler ve daha sonra ek bilgi sağlamak için arar ShowDetails . Üç sınıfın her biri bir ShowDetails yöntem tanımlar. new değiştirici, sınıfında ConvertibleCar tanımlamak ShowDetails için kullanılır. override değiştirici, sınıfında Minivan tanımlamak ShowDetails için kullanılır.

// Define the base class, Car. The class defines two methods,  
// DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived  
// class also defines a ShowDetails method. The example tests which version of  
// ShowDetails is selected, the base class method or the derived class method.  
class Car  
{  
    public void DescribeCar()  
    {  
        System.Console.WriteLine("Four wheels and an engine.");  
        ShowDetails();  
    }  
  
    public virtual void ShowDetails()  
    {  
        System.Console.WriteLine("Standard transportation.");  
    }  
}  
  
// Define the derived classes.  
  
// Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails  
// hides the base class method.  
class ConvertibleCar : Car  
{  
    public new void ShowDetails()  
    {  
        System.Console.WriteLine("A roof that opens up.");  
    }  
}  
  
// Class Minivan uses the override modifier to specify that ShowDetails  
// extends the base class method.  
class Minivan : Car  
{  
    public override void ShowDetails()  
    {  
        System.Console.WriteLine("Carries seven people.");  
    }  
}  

Örnek, hangi sürümünün ShowDetails çağrıldığını test ediyor. Aşağıdaki yöntemi, TestCars1her sınıfın bir örneğini bildirir ve ardından her örneği çağırır DescribeCar .

public static void TestCars1()  
{  
    System.Console.WriteLine("\nTestCars1");  
    System.Console.WriteLine("----------");  
  
    Car car1 = new Car();  
    car1.DescribeCar();  
    System.Console.WriteLine("----------");  
  
    // Notice the output from this test case. The new modifier is  
    // used in the definition of ShowDetails in the ConvertibleCar  
    // class.
  
    ConvertibleCar car2 = new ConvertibleCar();  
    car2.DescribeCar();  
    System.Console.WriteLine("----------");  
  
    Minivan car3 = new Minivan();  
    car3.DescribeCar();  
    System.Console.WriteLine("----------");  
}  

TestCars1 aşağıdaki çıkışı üretir. Özellikle beklediğiniz gibi olmayan sonuçlarına car2dikkat edin. nesnesinin türü şeklindedirConvertibleCar, ancak DescribeCar bu yöntem değiştiriciyle değil değiştiriciyle bildirildiğinden new sınıfında tanımlanan ConvertibleCar sürümüne ShowDetailsoverride erişmez. Sonuç olarak, bir ConvertibleCar nesne nesneyle aynı açıklamayı Car görüntüler. Bir nesne olan için car3sonuçların karşıtlığını Minivan belirleyin. Bu durumda, ShowDetails sınıfında bildirilen Minivan yöntemi sınıfında bildirilen Car yöntemini geçersiz kılar ShowDetails ve görüntülenen açıklama bir minivan açıklar.

// TestCars1  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Carries seven people.  
// ----------  

TestCars2 türüne Carsahip nesnelerin listesini oluşturur. Nesnelerin değerleri , ConvertibleCarve Minivan sınıflarından Carörneği oluşturulur. DescribeCar , listenin her öğesinde çağrılır. Aşağıdaki kod, tanımını TestCars2gösterir.

public static void TestCars2()  
{  
    System.Console.WriteLine("\nTestCars2");  
    System.Console.WriteLine("----------");  
  
    var cars = new List<Car> { new Car(), new ConvertibleCar(),
        new Minivan() };  
  
    foreach (var car in cars)  
    {  
        car.DescribeCar();  
        System.Console.WriteLine("----------");  
    }  
}  

Aşağıdaki çıkış görüntülenir. tarafından görüntülenen TestCars1çıkışla aynı olduğuna dikkat edin. nesnesinin ConvertibleCarConvertibleCartürü , veya Cariçinde olduğu gibi TestCars1olmasına bakılmaksızın sınıfının yöntemi çağrılmazTestCars2ShowDetails. Buna karşılık, car3 türü veya türü MinivanCarolsun, her iki durumda da sınıfından Minivan yöntemini çağırırShowDetails.

// TestCars2  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Carries seven people.  
// ----------  

Yöntemler TestCars3 ve TestCars4 örneği tamamlayın. Bu yöntemler, önce türü ConvertibleCar ve () olduğu bildirilen nesnelerden, sonra türü (TestCars3TestCars4) olarak bildirilen Car nesnelerden doğrudan çağrır ShowDetailsMinivan . Aşağıdaki kod bu iki yöntemi tanımlar.

public static void TestCars3()  
{  
    System.Console.WriteLine("\nTestCars3");  
    System.Console.WriteLine("----------");  
    ConvertibleCar car2 = new ConvertibleCar();  
    Minivan car3 = new Minivan();  
    car2.ShowDetails();  
    car3.ShowDetails();  
}  
  
public static void TestCars4()  
{  
    System.Console.WriteLine("\nTestCars4");  
    System.Console.WriteLine("----------");  
    Car car2 = new ConvertibleCar();  
    Car car3 = new Minivan();  
    car2.ShowDetails();  
    car3.ShowDetails();  
}  

Yöntemler, bu konudaki ilk örnekteki sonuçlara karşılık gelen aşağıdaki çıkışı oluşturur.

// TestCars3  
// ----------  
// A roof that opens up.  
// Carries seven people.  
  
// TestCars4  
// ----------  
// Standard transportation.  
// Carries seven people.  

Aşağıdaki kod, projenin tamamını ve çıkışını gösterir.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
  
namespace OverrideAndNew2  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // Declare objects of the derived classes and test which version  
            // of ShowDetails is run, base or derived.  
            TestCars1();  
  
            // Declare objects of the base class, instantiated with the  
            // derived classes, and repeat the tests.  
            TestCars2();  
  
            // Declare objects of the derived classes and call ShowDetails  
            // directly.  
            TestCars3();  
  
            // Declare objects of the base class, instantiated with the  
            // derived classes, and repeat the tests.  
            TestCars4();  
        }  
  
        public static void TestCars1()  
        {  
            System.Console.WriteLine("\nTestCars1");  
            System.Console.WriteLine("----------");  
  
            Car car1 = new Car();  
            car1.DescribeCar();  
            System.Console.WriteLine("----------");  
  
            // Notice the output from this test case. The new modifier is  
            // used in the definition of ShowDetails in the ConvertibleCar  
            // class.
            ConvertibleCar car2 = new ConvertibleCar();  
            car2.DescribeCar();  
            System.Console.WriteLine("----------");  
  
            Minivan car3 = new Minivan();  
            car3.DescribeCar();  
            System.Console.WriteLine("----------");  
        }  
        // Output:  
        // TestCars1  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Carries seven people.  
        // ----------  
  
        public static void TestCars2()  
        {  
            System.Console.WriteLine("\nTestCars2");  
            System.Console.WriteLine("----------");  
  
            var cars = new List<Car> { new Car(), new ConvertibleCar(),
                new Minivan() };  
  
            foreach (var car in cars)  
            {  
                car.DescribeCar();  
                System.Console.WriteLine("----------");  
            }  
        }  
        // Output:  
        // TestCars2  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Carries seven people.  
        // ----------  
  
        public static void TestCars3()  
        {  
            System.Console.WriteLine("\nTestCars3");  
            System.Console.WriteLine("----------");  
            ConvertibleCar car2 = new ConvertibleCar();  
            Minivan car3 = new Minivan();  
            car2.ShowDetails();  
            car3.ShowDetails();  
        }  
        // Output:  
        // TestCars3  
        // ----------  
        // A roof that opens up.  
        // Carries seven people.  
  
        public static void TestCars4()  
        {  
            System.Console.WriteLine("\nTestCars4");  
            System.Console.WriteLine("----------");  
            Car car2 = new ConvertibleCar();  
            Car car3 = new Minivan();  
            car2.ShowDetails();  
            car3.ShowDetails();  
        }  
        // Output:  
        // TestCars4  
        // ----------  
        // Standard transportation.  
        // Carries seven people.  
    }  
  
    // Define the base class, Car. The class defines two virtual methods,  
    // DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived  
    // class also defines a ShowDetails method. The example tests which version of  
    // ShowDetails is used, the base class method or the derived class method.  
    class Car  
    {  
        public virtual void DescribeCar()  
        {  
            System.Console.WriteLine("Four wheels and an engine.");  
            ShowDetails();  
        }  
  
        public virtual void ShowDetails()  
        {  
            System.Console.WriteLine("Standard transportation.");  
        }  
    }  
  
    // Define the derived classes.  
  
    // Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails  
    // hides the base class method.  
    class ConvertibleCar : Car  
    {  
        public new void ShowDetails()  
        {  
            System.Console.WriteLine("A roof that opens up.");  
        }  
    }  
  
    // Class Minivan uses the override modifier to specify that ShowDetails  
    // extends the base class method.  
    class Minivan : Car  
    {  
        public override void ShowDetails()  
        {  
            System.Console.WriteLine("Carries seven people.");  
        }  
    }  
  
}  

Ayrıca bkz.