Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Polimorfizm genellikle kapsülleme ve devralma sonrasında nesne odaklı programlamanın üçüncü yapı taşı olarak adlandırılır. Polimorfizm, "çok şekilli" anlamına gelen bir Yunanca kelimedir ve iki farklı yönü vardır:
- Çalışma zamanında, türetilmiş bir sınıfın nesneleri, yöntem parametreleri, koleksiyonlar veya diziler gibi yerlerde temel sınıfın nesneleri olarak kabul edilebilir. Bu çok biçimlilik oluştuğunda, nesnenin bildirilen türü artık çalışma zamanı türüyle aynı değildir.
- Temel sınıflarsanal yöntemleri tanımlayıp uygulayabilir ve türetilmiş sınıflar bunları geçersiz kılabilir, yani kendi tanımlarını ve uygulamalarını sağlarlar. Çalışma zamanında, istemci kodu yöntemini çağırdığında, CLR nesnenin çalışma zamanı türünü arar ve sanal yöntemin geçersiz kılmasını çağırır. Kaynak kodunuzda bir temel sınıfta bir yöntemi çağırabilir ve türetilmiş bir sınıfın yönteminin sürümünün yürütülmesine neden olabilirsiniz.
Sanal yöntemler, ilgili nesne gruplarıyla tekdüzen bir şekilde çalışmanızı sağlar. Örneğin, kullanıcının çizim yüzeyinde çeşitli şekiller oluşturmasına olanak tanıyan bir çizim uygulamanız olduğunu varsayalım. Derleme zamanında kullanıcının hangi şekil türlerini oluşturacağını bilmezsiniz. Ancak, uygulamanın oluşturulan tüm çeşitli şekil türlerini izlemesi ve bunları kullanıcı fare eylemlerine yanıt olarak güncelleştirmesi gerekir. Bu sorunu çözmek için iki temel adımda çok biçimlilik kullanabilirsiniz:
- Her bir şekil sınıfının ortak bir temel sınıftan türetildiği bir sınıf hiyerarşisi oluşturun.
- Temel sınıf yöntemine tek bir çağrı aracılığıyla türetilmiş herhangi bir sınıfta uygun yöntemi çağırmak için bir sanal yöntem kullanın.
İlk olarak, adlı Shapebir temel sınıf ve , Rectangleve Circlegibi Triangletüretilmiş sınıflar oluşturun. sınıfına Shape adlı Drawbir sanal yöntem verin ve sınıfın temsil ettiği belirli şekli çizmek için türetilmiş her sınıfta bunu geçersiz kılın. Bir List<Shape> nesne oluşturun ve nesnesine bir Circle, Triangleve Rectangle ekleyin.
public class Shape
{
// A few example members
public int X { get; init; }
public int Y { get; init; }
public int Height { get; init; }
public int Width { get; init; }
// Virtual method
public virtual void Draw()
{
Console.WriteLine("Performing base class drawing tasks");
}
}
public class Circle : Shape
{
public override void Draw()
{
// Code to draw a circle...
Console.WriteLine("Drawing a circle");
base.Draw();
}
}
public class Rectangle : Shape
{
public override void Draw()
{
// Code to draw a rectangle...
Console.WriteLine("Drawing a rectangle");
base.Draw();
}
}
public class Triangle : Shape
{
public override void Draw()
{
// Code to draw a triangle...
Console.WriteLine("Drawing a triangle");
base.Draw();
}
}
Çizim yüzeyini güncelleştirmek için foreach döngüsünü kullanarak Listedeki her nesnenin Shapebildirilen türü olsa da, çağrılacak olan çalışma zamanı türüdür (türetilmiş her sınıfta yöntemin geçersiz kılınan sürümü).
// Polymorphism at work #1: a Rectangle, Triangle and Circle
// can all be used wherever a Shape is expected. No cast is
// required because an implicit conversion exists from a derived
// class to its base class.
List<Shape> shapes =
[
new Rectangle(),
new Triangle(),
new Circle()
];
// Polymorphism at work #2: the virtual method Draw is
// invoked on each of the derived classes, not the base class.
foreach (var shape in shapes)
{
shape.Draw();
}
/* Output:
Drawing a rectangle
Performing base class drawing tasks
Drawing a triangle
Performing base class drawing tasks
Drawing a circle
Performing base class drawing tasks
*/
C# dilinde, kullanıcı tanımlı türler de dahil olmak üzere tüm türler öğesinden Objectdevraldığından her tür çok biçimli olur.
Çok biçimliliğe genel bakış
Sanal üyeler
Türetilmiş bir sınıf temel sınıftan devraldığında, temel sınıfın tüm üyelerini içerir. Temel sınıfta bildirilen tüm davranış türetilmiş sınıfın bir parçasıdır. Bu, türetilmiş sınıfın nesnelerinin temel sınıfın nesneleri olarak kabul edilmesine olanak tanır. Access değiştiricileri (public, protected, privatevb.), bu üyelerin türetilmiş sınıf uygulamasından erişilebilir olup olmadığını belirler. Sanal yöntemler tasarımcıya türetilmiş sınıfın davranışı için farklı seçenekler sunar:
- Türetilmiş sınıf, temel sınıftaki sanal üyeleri geçersiz kılabilir ve yeni davranış tanımlayabilir.
- Türetilmiş sınıf, mevcut davranışı koruyarak en yakındaki temel sınıfın yöntemini geçersiz kılmadan devralabilir, bu da daha fazla türetilmiş sınıfların yöntemi geçersiz kılmasına olanak tanır.
- Türetilmiş sınıf, temel sınıf uygulamalarını gizleyen üyelerin sanal olmayan yeni uygulamasını tanımlayabilir.
Türetilmiş bir sınıf, yalnızca temel sınıf üyesi sanal veya soyut olarak bildirilirse temel sınıf üyesini geçersiz kılabilir. Türetilmiş üye, yöntemin sanal çağırmaya katılmayı amaçladığını açıkça belirtmek için override anahtar sözcüğünü kullanmalıdır. Aşağıdaki kod bir örnek sağlar:
public class BaseClass
{
public virtual void DoWork() { }
public virtual int WorkProperty => 0;
}
public class DerivedClass : BaseClass
{
public override void DoWork() { }
public override int WorkProperty
{
get { return 0; }
}
}
Alanlar sanal olamaz; yalnızca yöntemler, özellikler, olaylar ve dizin oluşturucular sanal olabilir. Türetilmiş bir sınıf bir sanal üyeyi geçersiz kıldığında, bu sınıfın bir örneğine temel sınıfın bir örneği olarak erişildiğinde bile bu üye çağrılır. Aşağıdaki kod bir örnek sağlar:
DerivedClass B = new();
B.DoWork(); // Calls the new method.
BaseClass A = B;
A.DoWork(); // Also calls the new method.
Sanal yöntemler ve özellikler, türetilmiş sınıfların bir yöntemin temel sınıf uygulamasını kullanmaya gerek kalmadan temel sınıfı genişletmesini sağlar. Daha fazla bilgi için bkz . Geçersiz Kılma ve Yeni Anahtar Sözcüklerle Sürüm Oluşturma. Arabirim, uygulaması türetilmiş sınıflara bırakılan bir yöntem veya yöntem kümesi tanımlamak için başka bir yol sağlar.
Temel sınıf üyelerini yeni üyelerle gizleme
Türetilmiş sınıfınızın bir temel sınıftaki üyeyle aynı ada sahip bir üyeye sahip olmasını istiyorsanız, temel sınıf üyesini gizlemek için yeni anahtar sözcüğünü kullanabilirsiniz. anahtar new sözcüğü, değiştirilen bir sınıf üyesinin dönüş türünden önce yer alır. Aşağıdaki kod bir örnek sağlar:
public class BaseClass
{
public void DoWork() { WorkField++; }
public int WorkField;
public int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public new void DoWork() { WorkField++; }
public new int WorkField;
public new int WorkProperty
{
get { return 0; }
}
}
anahtar sözcüğünü new kullandığınızda, temel sınıf yöntemini geçersiz kılmadangizleyen bir yöntem oluşturursunuz. Bu, sanal yöntemlerden farklıdır. Yöntemi gizleme ile çağrılan yöntem, nesnesinin çalışma zamanı türüne değil değişkenin derleme zamanı türüne bağlıdır.
Gizli temel sınıf üyelerine, türetilmiş sınıfın örneği temel sınıfın bir örneğine dönüştürülerek istemci kodundan erişilebilir. Örneğin:
DerivedClass B = new();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Calls the old method.
Bu örnekte, her iki değişken de aynı nesne örneğine başvurur, ancak çağrılan yöntem değişkenin bildirilen türüne bağlıdır: DerivedClass.DoWork() değişken üzerinden DerivedClass erişildiğinde ve BaseClass.DoWork() değişken üzerinden BaseClass erişildiğinde.
Türetilmiş sınıfların sanal üyeleri geçersiz kılmasını engelleme
Sanal üyeler, sanal üye ile ilk olarak bunu bildiren sınıf arasında kaç sınıf bildirildiğinden bağımsız olarak sanal kalır. Sınıf A bir sanal üye bildirirse ve sınıf B sınıf A'den türetilirse, ve sınıf C sınıf B'den türetilirse, sınıf C sanal üyeyi devralır ve sınıf B bu üye için bir geçersiz kılma bildirip bildirmediğine bakılmaksızın geçersiz kılabilir. Aşağıdaki kod bir örnek sağlar:
public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}
Türetilmiş bir sınıf, geçersiz kılmayı korumalı olarak bildirerek sanal devralmayı durdurabilir. Devralmayı durdurmak için anahtar sözcüğün sealed sınıf üyesi bildiriminde anahtar sözcüğün override önüne koyulması gerekir. Aşağıdaki kod bir örnek sağlar:
public class C : B
{
public sealed override void DoWork() { }
}
Önceki örnekte yöntemi DoWork artık öğesinden Ctüretilen herhangi bir sınıf için sanal değildir. türüne veya türüne CBAgöre yayında olsalar bile örnekleri için sanaldır. Aşağıdaki örnekte gösterildiği gibi korumalı yöntemler anahtar sözcüğü kullanılarak new türetilmiş sınıflarla değiştirilebilir:
public class D : C
{
public new void DoWork() { }
}
Bu durumda, türünde DoWorkbir değişken kullanılarak çağrılırsa DD, yeni DoWork çağrılır. Eğer C, B veya A türündeki bir değişken, D örneğine erişmek için kullanılıyorsa, DoWork'e yapılan bir çağrı, sanal devralma kurallarına göre hareket eder ve bu çağrıları C sınıfındaki DoWork implementasyonuna yönlendirir.
Türetilmiş sınıflardan temel sınıf sanal üyelerine erişme
Bir yöntemin veya özelliğin yerini alan veya geçersiz kılan türetilmiş bir sınıf, anahtar sözcüğünü kullanarak temel sınıftaki yönteme veya özelliğe erişmeye base devam edebilir. Aşağıdaki kod bir örnek sağlar:
public class Base
{
public virtual void DoWork() {/*...*/ }
}
public class Derived : Base
{
public override void DoWork()
{
//Perform Derived's work here
//...
// Call DoWork on base class
base.DoWork();
}
}
Daha fazla bilgi için bkz . base.
Not
Sanal üyelerin kendi uygulamalarında bu üyenin temel sınıf uygulamasını çağırmak için kullanmaları base önerilir. Temel sınıf davranışının oluşmasına izin vermek, türetilmiş sınıfın türetilmiş sınıfa özgü davranışı uygulamaya odaklanmasını sağlar. Temel sınıf uygulaması çağrılmazsa, davranışlarını temel sınıfın davranışıyla uyumlu hale getirmek türetilmiş sınıfa kadar olur.