Menu

C# Abstract Class: Abstract Metotlar, Örnekler ve Interface Farkı

C#'ta abstract sınıf nedir: örneklenemeyen ve türetilmiş sınıflarının uygulaması gereken abstract üyeler bildirebilen bir temel sınıf. Abstract metotlar ve property'ler, constructor'lar, şablon metot kalıbı ve bunun yerine ne zaman interface seçileceği.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Bir abstract sınıf yalnızca türetilmek için var olan bir sınıftır. Örneklenemez ve abstract üyeler bildirebilir: her somut türetilmiş sınıfın uygulaması gereken, gövdesi olmayan metotlar ve property'ler. Onunla ilgili geri kalan her şey sıradan bir sınıftır: alanları, constructor'ları ve türetilmiş sınıfların kalıtım aldığı tamamen uygulanmış metotları olabilir.

Bir abstract sınıf bildirmek

Sınıfı abstract işaretleyin ve türetilmiş sınıfların sağlaması gereken her üyeyi abstract işaretleyip gövde yerine noktalı virgülle bitirin:

Çıktı:

Circle: area 7.07, perimeter 9.42
Rectangle: area 10.00, perimeter 13.00

Describe temel sınıfta bir kez yazılmıştır ve Shape'te hiç var olmayan Area ile Perimeter'ı çağırır. Abstract bir üyenin amacı budur: temel sınıf ona güvenebilir ve derleyici her somut şeklin onu sağladığını garanti eder. Birini unutan türetilmiş bir sınıf derlenmez:

class Triangle : Shape
{
    public Triangle() : base("Triangle") { }
    public override double Area() => 6;
}
// error CS0534: 'Triangle' does not implement inherited abstract member 'Shape.Perimeter()'

Çözüm Perimeter'ı uygulamak ya da başka sınıflar için bir ara temelse Triangle'ın kendisini abstract işaretlemektir.

Abstract üyelerin kuralları

  • Abstract bir üyenin gövdesi yoktur ve örtük olarak virtual'dır: türetilmiş sınıflar onu override ile uygular.
  • Yalnızca abstract sınıflar abstract üye içerebilir. Normal bir sınıfa koymak derleme hatasıdır.
  • Abstract üyeler private olamaz (kimse onları override edemezdi) ve bir sınıfta static olamaz.
  • Metotlar, property'ler, indeksleyiciler ve event'ler abstract olabilir. Alanlar ve constructor'lar olamaz.
  • Bir abstract sınıfın herhangi bir abstract üye içermesi gerekmez. Bir sınıfı yalnızca abstract işaretlemek örneklemeyi engeller; bu, yalnızca alt sınıfları aracılığıyla anlam kazanan bir temel sınıf için işe yarar.

Abstract bir property, türetilmiş sınıfın hangi erişimcileri sağlaması gerektiğini bildirir:

abstract class Plan
{
    public abstract decimal MonthlyPrice { get; }
    public abstract string Name { get; }
}

class ProPlan : Plan
{
    public override decimal MonthlyPrice => 12.99m;
    public override string Name => "Pro";
}

Abstract sınıflarda constructor'lar

Bir abstract sınıfın constructor'ları olabilir. new ile çağrılamazlar, ama her türetilmiş constructor : base(...) aracılığıyla birini çalıştırır; bu yüzden paylaşılan durumun başlatıldığı ve doğrulandığı yerdirler. Onları protected bildirin; bu tam olarak şunu söyler: bunu yalnızca türetilmiş sınıflar kullanabilir.

Şablon metot kalıbı

Abstract bir sınıf yazmanın en yaygın nedeni, bir algoritmanın sırasını temel sınıfta sabitlemek ve tek tek adımları türetilmiş sınıfların doldurmasına izin vermektir. Adımları çalıştıran temel metot virtual değildir, bu yüzden hiçbir alt sınıf onları yeniden sıralayamaz ya da atlayamaz.

Çıktı:

item,qty,price
Coffee beans,2,11.50
Filter papers,1,3.20

| Item | Qty | Price |
| --- | --- | --- |
| Coffee beans | 2 | 11.50 |
| Filter papers | 1 | 3.20 |

Total: 26.20

Her satır adlandırılmış bir tuple'dır ve çıktı bir StringBuilder ile oluşturulur. Karışıma dikkat edin: Header ve Row abstract'tır, çünkü her biçim onlara karar vermelidir; Footer ise boş bir varsayılanla virtual'dır, çünkü çoğu biçimin orada hiçbir şeye ihtiyacı yoktur. Adımlar protected'tır, bu yüzden dışarıdaki kod yalnızca Export'u çağırabilir. Framework sınıfları aynı fikri kullanır: Stream ve TextWriter, birçok kolaylık metodu türetilmiş bir sınıfın sağladığı birkaç üye (bir stream için Read ve Write, bir text writer için Write(char)) üzerine kurulu abstract temel sınıflardır.

Abstract sınıf ile interface

İkisi de somut sınıfı bilmeden bir tipe karşı kod yazmanızı sağlar. Ne içerebildikleri ve bir sınıfın kaç tanesine sahip olabileceği bakımından farklılaşırlar:

Abstract sınıfInterface
Bir sınıfın kalıtım alabileceği ya da uygulayabileceğibirçok
Örnek alanları (durum)evethayır
Constructor'larevethayır
Gövdeli metotlarevetevet, C# 8'den beri (varsayılan interface metotları)
Statik üyelerevetevet, C# 8'den beri; C# 11'den beri static abstract üyeler
Üyelerde erişim belirleyicilerhepsivarsayılan olarak public; C# 8'den beri diğerlerine izin verilir
Struct'lar kullanabilirhayırevet
Sonradan üye eklemekabstract değilse güvenlivarsayılan gövdesi yoksa uygulayanları bozar

Varsayılan interface metotları (C# 8) aradaki farkı daralttı, ama temel farkı değil:

public interface ILogger
{
    void Write(string message);
    void Error(string message) => Write("ERROR: " + message);   // default implementation: C# 8, .NET Core 3.0+
}

Varsayılan bir metot yine de örnek alanlarına dokunamaz, çünkü interface'in hiç alanı yoktur; yalnızca interface'in diğer üyelerini çağırabilir.

Seçmenin pratik bir yolu:

  • İlgisiz tiplerin sahip olabileceği bir yeteneği (IComparable<T>, IDisposable, IShippingProvider) tanımlarken, struct'ların katılabilmesi gerektiğinde ya da bir sınıfın böyle birkaç role ihtiyacı olduğunda interface. Dependency injection kodunun çoğunun interface'lere karşı yazılmasının nedeni budur.
  • Türetilmiş tipler gerçekten tek bir şeyin varyasyonları olduğunda ve durumu ya da sabit bir algoritmayı paylaştığında, yukarıdaki exporter'lar gibi, abstract sınıf.
  • İkisi birden yaygındır: çağıranların bağımlı olacağı bir interface ve onu uygulayıp uygulayanları paylaşılan kısımları yeniden yazmaktan kurtaran abstract bir temel sınıf. Interface'ler sayfası interface tarafını ayrıntılı ele alır.

Yaygın hatalar

  • Temel sınıfı örneklemeye çalışmak. new Shape(...) CS0144'tür. Türetilmiş bir sınıfı örnekleyin.
  • Uygulamada override'ı unutmak. Türetilmiş sınıfta public double Area() yazmak abstract üyeyi uygulamaz; derleyici eksik uygulama için CS0534 bildirir, ayrıca yeni metodun kalıtılanı gizlediğine dair bir uyarı verir.
  • Abstract bir sınıfta public bir constructor. Zararsız ama yanıltıcı. protected kullanın.
  • Paylaşılan kodu olmayan abstract sınıflar. Temel sınıfın yalnızca abstract üyeleri varsa ve durumu yoksa, bir interface aynı şeyi söyler ve tek temel sınıf hakkını harcamaz.
  • Temel constructor'dan abstract üyeleri çağırmak. Türetilmiş uygulama türetilmiş constructor'ın gövdesinden önce çalışır, bu yüzden o gövdenin atadığı alanlar hâlâ 0 ya da null'dır.

Sıkça Sorulan Sorular

C#'ta abstract sınıf nedir?

abstract işaretli bir sınıf yalnızca temel sınıf olarak tasarlanmıştır: ondan new ile bir örnek oluşturamazsınız (CS0144 hatası). Normal alanlar, constructor'lar ve metotlar içerebilir; ayrıca gövdesi olmayan ve abstract olmayan her türetilmiş sınıfın uygulaması gereken abstract üyeler de içerebilir.

C#'ta abstract sınıf ile interface arasındaki fark nedir?

Bir sınıf yalnızca bir abstract sınıftan türeyebilir ama birçok interface uygulayabilir. Bir abstract sınıf durum (örnek alanları), constructor'lar ve her erişim seviyesinde üyeler tutabilir ve paylaşılan uygulama için doğal yerdir. Bir interface örnek durumu olmayan bir yeteneği tanımlar; C# 8'den beri varsayılan metot gövdeleri içerebilir, ama yine de örnek alanlarına ya da constructor'lara sahip olamaz.

C#'ta abstract ile virtual metotlar arasındaki fark nedir?

Bir virtual metodun türetilmiş sınıfların override edebileceği bir gövdesi vardır. Bir abstract metodun gövdesi yoktur ve türetilmiş sınıflar onu override etmek zorundadır; aksi halde kendileri abstract olurlar (somut bir sınıf için CS0534 hatası). Abstract metotlar yalnızca abstract sınıflarda bulunabilir.

C#'ta bir abstract sınıfın constructor'ı olabilir mi?

Evet. Türetilmiş bir sınıf oluşturulurken : base(...) aracılığıyla çalışır ve genellikle paylaşılan alanları başlatır. Onu protected bildirin: bir abstract sınıftaki public bir constructor çağıranların onu kullanabileceğini ima eder, oysa kullanamazlar.

Bir abstract sınıfın örneği neden oluşturulamaz?

Çünkü uygulaması olmayan abstract üyeleri olabilir: new Shape().Area() çağrısının çalıştıracağı bir kod olmazdı. Derleyici CS0144 bildirir ("Cannot create an instance of the abstract type or interface"). Bunun yerine somut bir türetilmiş sınıfın örneğini oluşturun ve isterseniz onu abstract tipte bir değişkende tutun: Shape s = new Circle(2);.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA