"Soyut sınıf" ve "arayüz" benzer kavramlardır, arayüz ise ikisinin daha soyutudur. Farklılaşan bir faktör, soyut sınıfların gerektiğinde türetilmiş sınıflar için yöntem uygulamaları sağlamasıdır. Bununla birlikte, C # 'da, bu farklılaştırma faktörü, arayüz metotları için uygulamaların temin edilmesine olanak tanıyan, uzatma yöntemlerinin yakın zamanda sunulmasıyla azaltılmıştır. Bir başka ayırt edici faktör, bir sınıfın yalnızca bir soyut sınıfı miras alabilmesi (yani, çoklu kalıtım yoktur), ancak çoklu arayüzler uygulayabilmesidir. Bu, arayüzleri daha az kısıtlayıcı ve daha esnek hale getirir. Peki, C # 'da, uzantı yöntemleriyle arabirimler yerine soyut sınıfları ne zaman kullanmalıyız?
Arabirim + uzantı yöntemi modelinin dikkate değer bir örneği LINQ'dur ve burada
IEnumerable uygulayan herhangi bir tür için sorgu işlevselliği çok sayıda uzantı yöntemi aracılığıyla sağlanır.
Uygulanacak sınıfın bir bölümüne ihtiyacınız olduğunda. Kullandığım en iyi örnek şablon yöntemi modelidir.
public abstract class SomethingDoer { public void Do() { this.DoThis(); this.DoThat(); } protected abstract void DoThis(); protected abstract void DoThat(); }
Böylece, nasıl uygulanacaklarının ayrıntılarını bilmeden Do () çağrıldığında atılacak adımları tanımlayabilirsiniz. Sınıf türetme, soyut yöntemleri uygulamalı, ancak Do () yöntemini uygulamamalıdır.
Genişletme yöntemleri mutlaka denklemin "sınıfın bir parçası olmalı" kısmını karşılamaz. Ayrıca, iirc, uzantı yöntemleri, kapsamı dışında herkesten başka bir şey olamaz.
düzenlemek
Soru, başlangıçta kredi verdiğimden daha ilginç. Daha ayrıntılı bir incelemede, Jon Skeet cevaplandı SO arayüzleri + uzatma yöntemlerini kullanma lehine böyle bir soru) Ayrıca, bir potansiyel dezavantaj bu şekilde tasarlanmış bir nesne hiyerarşisine karşı yansıma kullanıyor.
Şahsen, şu anda yaygın olan bir uygulamayı değiştirmenin faydasını görmekte sorun yaşıyorum, ancak bunu yaparken de çok az veya hiç dezavantaj yok.
Utility sınıfları aracılığıyla bu şekilde birçok dilde programlamanın mümkün olduğuna dikkat edilmelidir. Uzantılar, yöntemlerin sınıfa ait gibi görünmesi için sözdizimsel şekeri sağlar.
Her şey ne modellemek istediğiniz:
Soyut sınıflar kalıtım ile çalışır. Sadece özel temel sınıflar olarak, bazı is-a - ilişkilerini modeller.
Örneğin, bir köpek is bir hayvan, bu yüzden
class Dog : Animal { ... }
Aslında create genel bir tüm hayvana (neye benzeyecek?) Mantıklı olmadığından, bu
Animal temel sınıfı
abstract - yapıyoruz ama hala bir temel sınıf. Ve
Dog sınıfı,
Animal olmadan mantıklı değil.
Öte yandan öte yandan farklı bir hikaye. Kalıtım kullanmazlar, ancak polimorfizm (ki bu can kalıtımla da uygulanabilir). Bir is-a ilişkisini modellemezler, ancak daha fazla destekliyor.
Örneğin;
IComparable - bir başkasıyla karşılaştırmayı destekleyen bir nesne.
Bir sınıfın işlevselliği bağımlı değildir uyguladığı arabirimlere, arabirim işlevselliğe erişmek için genel bir yol sağlar.
Dispose veya
Graphics’nin
FileStream’ini
IDisposable’i uygulamalarına gerek kalmadan yine de yapabiliriz. arayüz sadece ilişkilidir yöntemleri birlikte.
Prensip olarak, bir sınıfın davranışını değiştirmeden sadece ona erişimi zenginleştirmeden arayüzler gibi arayüzler eklenebilir ve kaldırılabilir. Nesne anlamsız olacağından temel sınıfı alamazsınız!
Yıllar içinde soyut dersleri (en azından yaratılmamış) kullanmadığımı fark ettim.
Soyut sınıf arayüz ve uygulama arasında biraz garip bir canavar. Soyut sınıflarda örümcek anlayışımı karıncalayan bir şey var. Ben iddia ediyorum, herhangi bir şekilde (veya herhangi bir bağlantı yapmak) arayüzü arkasındaki uygulama "maruz" olmamalıdır.
Bir arabirimi uygulayan sınıflar arasında ortak davranışa ihtiyaç olsa bile, soyut bir sınıftan ziyade bağımsız bir yardımcı sınıf kullanırdım.
Arayüzlere giderdim.
IMHO, bence burada kavramların bir karışımı var.
Arabirimler farklı türde bir kalıtım kullanırken, sınıflar belirli bir miras kullanır.
Her iki kalıtım türü de önemli ve yararlıdır ve her birinin artıları ve eksileri vardır.
En baştan başlayalım.
Arayüzlerle hikaye C++ ile uzun bir süre önce başlıyor. 1980'lerin ortalarında, C++ geliştirildiğinde, farklı bir tür olarak arayüzler fikri henüz gerçekleşmedi (zamanla gelecekti).
C++ yalnızca bir tür mirasa, sınıflar tarafından kullanılan ve miras olarak adlandırılan miras türüne sahipti.
GoF Book tavsiyesini uygulayabilmek için: "Uygulama için değil, arayüz için programlamak için", C++, C # 'da hangi arayüzleri yapabilme yeteneğine sahip (ve yararlı!) Yapabilmek için soyut sınıfları ve çoklu uygulama kalıtımını destekledi. .
C # yeni bir tür, arayüzler ve yeni bir kalıtım, arayüz kalıtım, "önemli bir uyarı ile" Uygulama için değil program için "programlamak için destek için en az iki farklı yol sunar: C # arayüz devralma ile çoklu kalıtım (uygulama devralma ile değil) destekler.
Yani, C # 'daki arayüzlerin arkasındaki mimari nedenler GoF önerisidir.
Umarım bu yardımcı olabilir.
Saygılarımla, Gastón
Bir arabirime uzantı yöntemleri uygulamak, yalnızca ortak bir arabirimi paylaşabilecek sınıflar arasında ortak davranış uygulamak için kullanışlıdır. Bu tür sınıflar zaten var olabilir ve başka yollarla uzantılara kapalı olabilir.
Yeni tasarımlar için arayüzlerde uzatma yöntemlerinin kullanılmasını tercih ederim. Türler hiyerarşisi için, uzantı yöntemleri, değişiklik için tüm hiyerarşiyi açmak zorunda kalmadan davranışı genişletmek için bir yol sağlar.
Ancak, uzantı yöntemleri özel uygulamaya erişemez, bu nedenle bir hiyerarşinin en üstünde, özel uygulamayı genel bir arabirimin arkasına kapsüllemek gerekirse, soyut bir sınıf tek yol olacaktır.
Ben C # çoklu miras desteklenmediğini düşünüyorum ve bu yüzden arayüz kavramı C # tanıttı.
Soyut sınıflar söz konusu olduğunda, çoklu kalıtım da desteklenmez. Bu nedenle soyut sınıfların veya arayüzlerin kullanılıp kullanılmayacağına karar vermek kolaydır.