Bir arabirim ile sınıf arasındaki fark nedir ve yöntemleri doğrudan sınıfta uygulayabildiğimde neden bir arabirim kullanmalıyım?


118

Bunun çok basit bir soru olduğunun farkındayım, ancak bir görüşmeci bana çok hileli bir şekilde sordu ve ben çaresizdim :(

Bir arayüzün sadece materyal veya teorik tanımını biliyorum ve üzerinde çalıştığım birçok projede de uyguladım. Ama bunun neden ve nasıl yararlı olduğunu gerçekten anlamıyorum.

Ayrıca arayüzdeki bir şeyi anlamıyorum. örneğin, kullanıyoruz

conn.Dispose();nihayet blokta. Ama bu sınıfın IDisposableinterface ( SqlConnection) sınıfını uyguladığını veya miras aldığını görmüyorum yani. Yöntem adını nasıl arayabileceğimi merak ediyorum. Aynı şekilde, Dispose yönteminin nasıl çalıştığını anlamıyorum, çünkü tüm arayüz yöntemleri için işlev gövdesini kendi uygulamamızla uygulamamız gerekiyor. Peki, Arayüzler nasıl sözleşme olarak kabul edilir veya adlandırılır? Bu sorular şimdiye kadar aklımda yuvarlanmaya devam etti ve açıkçası sorularımı anlayabileceğim bir şekilde açıklayacak iyi bir konu görmedim.

Her zamanki gibi MSDN çok korkutucu görünüyor ve tek bir satır net değil ( Arkadaşlar, üst düzey geliştirme ile ilgilenenleri nazikçe mazur görün, herhangi bir kodun veya makalenin onu gören herkesin zihnine ulaşması gerektiğini kuvvetle hissediyorum, dolayısıyla diğerlerinin dediği gibi, MSDN kullanım dışı ).

Görüşmeci şunları söyledi:

5 yöntemi vardır ve bunu doğrudan sınıfta uygulamaktan mutluluk duyar, ancak Soyut sınıf veya arayüze gitmeniz gerekiyorsa, hangisini seçersiniz ve neden? Çeşitli bloglarda okuduğum her şeyi hem soyut sınıfın hem de arayüzün avantaj ve dezavantajlarını söyleyerek cevapladım ama ikna olmadı, genel olarak "Neden Arayüz" ü anlamaya çalışıyor. Genel olarak "neden soyut sınıf", aynı yöntemleri yalnızca bir kez uygulayabilsem ve onu değiştirmeyeceğim.

Net olarak hiçbir yerde göremiyorum, arayüzler ve işleyişi hakkında beni net bir şekilde açıklayacak bir makale bulabildim. Arayüzler hakkında hala bilgisi olmayan (kullandığım teorik ve yöntemleri biliyorum) ama bunu net bir şekilde anladığımdan memnun olmayan birçok programcıdan biriyim.


4
Arayüzler de anlamakta zorlandığım bir tanesidir. İyi soru.
Brian

4
somut bir uygulama yerine soyut bir sözleşmeye programlama .... Kısacası, bir arayüz gerekli olduğunda bir arayüz uygulayan herhangi bir nesneyi değiştirebileceğiniz anlamına gelir.
Mitch Wheat

7
SqlConnectionSystem.ComponentModel.Componenthangi uygulayan devralır IDisposable.
Lee

2
@MitchWheat - Örnek olması amaçlanmadı, soru nasıl SqlConnectionuygulandığını soruyor IDisposable.
Lee

Oh Lee, teşekkür ederim anlamamı sağladı. Ama yine de "Dispose" yöntemi işlevselliğinin nasıl ve nerede tanımlandığını göremiyorum.
Öğrenci

Yanıtlar:


92

Buna benzer bir şey oluşturmak istediğinizde arayüzler mükemmeldir:

using System;

namespace MyInterfaceExample
{
    public interface IMyLogInterface
    {
        //I want to have a specific method that I'll use in MyLogClass
        void WriteLog();       
    }

    public class MyClass : IMyLogInterface
    {

        public void WriteLog()
        {
            Console.Write("MyClass was Logged");
        }
    }

    public class MyOtherClass : IMyLogInterface
    {

        public void WriteLog()
        {
            Console.Write("MyOtherClass was Logged");
            Console.Write("And I Logged it different, than MyClass");
        }
    }

    public class MyLogClass
    {
        //I created a WriteLog method where I can pass as a parameter any object that implements IMyLogInterface.
        public static void WriteLog(IMyLogInterface myLogObject)
        {
            myLogObject.WriteLog(); //So I can use WriteLog here.
        }
    }

    public class MyMainClass
    {
        public void DoSomething()
        {
            MyClass aClass = new MyClass();
            MyOtherClass otherClass = new MyOtherClass();

            MyLogClass.WriteLog(aClass);//MyClass can log, and have his own implementation
            MyLogClass.WriteLog(otherClass); //As MyOtherClass also have his own implementation on how to log.
        }
    }
}

Örneğimde MyLogClass, yazan bir geliştirici olabilirim ve diğer geliştiriciler sınıflarını oluşturabilir ve günlüğe kaydetmek istediklerinde arayüzü uygularlar IMyLogInterface. WriteLog()Metodu kullanmak için neyi uygulamaya ihtiyaç duyduklarını soruyorlardı MyLogClass. Arayüzde bulacakları cevap.


3
Hey bu benim anlamam için çok iyi bir içerik gibi görünüyor, gerçekten minnettarım, çok teşekkürler :) :)
Öğrenci

14
Sorum şu ki, eğer örnekleme yapıyorsanız MyClassve MyOtherClassneden aClass.WriteLog()bu fazladan adımı neden eklemiyorsunuz? Uygulamasının WriteLog()her sınıf için farklı kalması gerekir, ancak zaten nesneye sahipsiniz, öyleyse neden onu bir eylemci sınıfına aktarasınız?
Zach M.

Hm, günlük kaydı örneğinizi külçe üzerine koyarsanız, diğerlerinin ayrıntılarını bilmeden kaydedicinizi kullanması daha kolay olurdu .. ama diğer yandan, yine de evrensel bir sınıf değil (ea arabirim ve alerji düzeyleri) arabirimler hala yalnızca kapsamınız dahilindedir. yani sizden başka kimler bundan yararlanıyor?
user3800527

2
@ZachM. Haklıysam, cevabın anlamı, sınıfları başlatmayacak, ancak diğer geliştiriciler sınıfları başlatacak ve onu MyLogClass WriteLogyönteme parametre olarak geçirecek . Dolayısıyla yöntemi, uygulayan herhangi bir nesneyi idare edebilir IMyLogInterface. İşte başka bir ilginç gönderi.
shaijut

1
Sorum neden Arayüz ??? Yukarıdaki senaryo, tüm soyut yöntemlerle soyut bir sınıfla da elde edilebilir.
Abhijit Ojha

52

Arayüz kullanmamın bir nedeni, kodun esnekliğini artırmasıdır. Diyelim ki, Hesap sınıfı türünde bir nesneyi parametre olarak alan bir yöntemimiz var, örneğin:

public void DoSomething(Account account) {
  // Do awesome stuff here.
}

Bununla ilgili sorun, yöntem parametresinin bir hesabın uygulanmasına doğru sabitlenmesidir. Başka türden bir hesaba asla ihtiyacınız yoksa bu sorun değil. Bunun yerine parametre olarak bir hesap arayüzü kullanan bu örneği ele alalım.

public void DoSomething(IAccount account) {
  // Do awesome stuff here.
}

Bu çözüm bir uygulamaya yönelik değildir, bu da ona bir SuperSavingsAccount veya bir ExclusiveAccount (her ikisi de IAccount arayüzünü uygular) geçirebileceğim ve uygulanan her hesap için farklı davranışlar elde edebileceğim anlamına gelir.


45

Arayüzler , uygulayıcıların uyması gereken sözleşmelerdir. Soyut sınıflar sözleşmelere ve paylaşılan uygulamalara izin verir - bu, Arabirimlerin sahip olamayacağı bir şeydir. Sınıflar birden çok arabirimi uygulayabilir ve devralabilir. Sınıflar yalnızca tek bir soyut sınıfı genişletebilir.

Neden Arayüz

  • Varsayılan veya paylaşılan kod uygulamanız yok
  • Veri sözleşmelerini paylaşmak istiyorsunuz (web hizmetleri, SOA)
  • Her arayüz Uygulayacak kişi için farklı uygulamaları (varsa IDbCommandvardır SqlCommandve OracleCommandbelirli şekillerde arabirimini uygulamak hangi )
  • Birden çok mirası desteklemek istiyorsunuz .

Neden Soyut

  • Varsayılan veya paylaşılan kod uygulamanız var
  • Kod tekrarını en aza indirmek istiyorsunuz
  • Sürüm oluşturmayı kolayca desteklemek istiyorsunuz

2
@Silver Bloglara yazdıklarınızın çoğunu okudum ama pratik olarak anlamaya çalışıyorum. WCF hizmetleri yaptım, arayüzleri açığa çıkardım (Ancak, yukarı veya aşağı akış olmadan yalnızca tek bir bağımsız uygulamaydı). Dolayısıyla arayüzleri çok iyi tasarlamama ve uygulamama rağmen tam olarak anlayamadım. Sorum şu ki, pratikte, sadece sözleşme anlamına gelen yöntem isimlerini paylaşıyorsunuz değil mi? BU NASIL YARARLI :( Sadece tüm yöntemleri uygulamaya zorladığını biliyorum, ama başka nasıl? Arayüzdeki 2. nokta paylaş diyor, bunun pratik bir gerçek zamanlı örneği verebilir misin
Öğrenci

1
Arayüzleri ve SOA ile ilgili pratik Örneğin, bizim WCF Arayüzleri paylaşan ( DataContractsbir .NET Meclisi (in) örneğin Contracts.Shared.dll o .NET istemci tüketicilerin kolayca böylece) Interoperate kullanarakChannelFactory ( vb Ekleme Servis Referans aracılığıyla üreten kodunu kaçınarak ) veya Paylaşılan
Türlerle

Soyut bir cals içinde yalnızca soyut yöntemleri bildireceksem, soyut sınıf arayüz görevi görecek, o zaman neden arayüze ihtiyacımız var?
Abhijit Ojha

25

görüntü açıklamasını buraya girin

Dolayısıyla bu örnekte, PowerSocket diğer nesneler hakkında başka hiçbir şey bilmiyor. Nesnelerin tümü PowerSocket tarafından sağlanan Güce bağlıdır, bu nedenle IPowerPlug'ı uygular ve böylece ona bağlanabilirler.

Arayüzler yararlıdır çünkü nesnelerin birbirleri hakkında başka bir şey bilmelerine gerek kalmadan birlikte çalışmak için kullanabilecekleri sözleşmeler sağlarlar.


Bu mantıklı, ancak hala anlamakta zorlanıyorum, PowerSocket için bir temel sınıf yaratmaz mısınız ve diğer tüm şeyler gerekirse onu miras alır mı? Teknik olarak Elektrik Prizlerinin diğer sınıflar hakkında hiçbir fikri yoktur.
altaaf.hussein

Sanırım C #'da çoklu mirasa izin verilmediğinden
Hugh Seagraves

22

Tek kelimeyle - Polimorfizm nedeniyle !

"Bir Arayüze Programlıyorsanız, Uygulama Değil" ise, aynı arayüzü (tip) paylaşan farklı nesneleri argüman olarak yönteme enjekte edebilirsiniz. Bu şekilde, yöntem kodunuz başka bir sınıfın herhangi bir uygulamasıyla birleştirilmez; bu, her zaman aynı arayüzün yeni oluşturulan nesneleriyle çalışmaya açık olduğu anlamına gelir. (Açma / Kapama Prensibi)

  • Bağımlılık Enjeksiyonuna bakın ve kesinlikle Tasarım Desenleri - GOF'un Yeniden Kullanılabilir Nesne Yönelimli Yazılım Öğeleri bölümünü okuyun .

4

C # 'da ördek yazımı yoktur - belirli bir yöntemin bir dizi somut sınıfta uygulandığını bilmeniz, bu yöntemi çağırma konusunda hepsini aynı şekilde ele alabileceğiniz anlamına gelmez. Bir arabirim uygulamak, onu uygulayan tüm sınıfları, arabirimin tanımladığı şeyle ilgili olarak aynı tür bir şey olarak ele almanıza olanak tanır.


3
Dinamik türle .net4 biçiminde bir tür ördek türü elde edebilirsiniz.
Tony Hopkinson

4

Bu soruları sorarken çok fazla kan döküldüğüne inanıyorum ve birçoğu bu sorunları normal bir insanın anlayamayacağı robot benzeri terimleri açıklayarak çözmeye çalışıyor.

Yani İlk. neden arayüz ve neden soyut olduğunu öğrenmek için bunların ne işe yaradığını öğrenmeniz gerekir. Ben şahsen bu ikisini Fabrika Sınıfını uygularken öğrendim. bu linkte iyi bir tuturial buluyorsun

Şimdi daha önce verdiğim bağlantıya temel atalım.

You have Araç ekleme gibi (kullanıcı gereksinimi üzerine değişebilir sınıfı Truck , Tank , Airplane vb Ve sahip olduğumuz verilen

public class clsBike:IChoice
{
   #region IChoice Members
    public string Buy()
    {
       return ("You choose Bike");
    }
    #endregion
}

ve

public class clsCar:IChoice
{
   #region IChoice Members
    public string Buy()
    {
       return ("You choose Car");
    }
    #endregion
}

ve her ikisi de sadece Sınıfımın Satın Alma yöntemine sahip olması gerektiğini söyleyen Sözleşme IChoice'ye sahiptir

public interface IChoice
{
    string Buy();
}

Şimdi, görüyorsunuz, bu arabirim yalnızca yöntemi zorlar, Buy()ancak miras alınan sınıfın onu uyguladıklarında ne yapacağına karar vermesine izin verir. Bu, Arayüzün sınırlamasıdır, tamamen arayüz kullanarak, abstact kullanarak otomatik olarak uygulayabileceğimiz bazı görevleri tekrarlamak zorunda kalabilirsiniz. Örneğimizde, diyelim ki, her aracı satın alırken bir indirim var.

public abstract class Choice
{
    public abstract string Discount { get; }
    public abstract string Type { get; }
    public string Buy()
    {
       return "You buy" + Type + " with " + Discount;
}
public class clsBike: Choice
{
    public abstract string Discount { get { return "10% Discount Off"; } }
    public abstract string Type { get { return "Bike"; } }
}

public class clsCar:Choice
{
    public abstract string Discount { get { return " $15K Less"; } }
    public abstract string Type { get { return "Car"; } }
}

Şimdi Fabrika Sınıfını kullanarak, aynı şeyi elde edebilirsiniz, ancak soyut kullanarak, temel sınıfın Buy()yöntemi yürütmesine izin verirsiniz .

Özetle: Arayüz sözleşmeleri, uygulamayı miras sınıfının yapmasına izin verirken Soyut sınıf Sözleşmeleri uygulamayı başlatabilir (bu, Inherit sınıfı tarafından geçersiz kılınabilir)


2

Bir arayüz ile şunları yapabilirsiniz:

1) Uygulamanızın farklı kesimlerini sunan ve daha uyumlu bir arayüz sağlayan ayrılmış arayüzler oluşturun.

2) Arayüzler arasında aynı ada sahip birden fazla yönteme izin verin, çünkü sizin çakışan bir uygulamaya sahip değilsiniz, sadece bir imza var.

3) Arayüzünüzü uygulamanızdan bağımsız olarak versiyonlayabilir ve çıkarabilir, böylece bir sözleşmenin yerine getirilmesini sağlayabilirsiniz.

4) Kodunuz somutlaştırmadan ziyade soyutlamaya dayanabilir ve test Mocks enjekte etme vb. Dahil olmak üzere akıllı bağımlılık enjeksiyonuna izin verir.

Emin olduğum daha birçok neden var, bunlar sadece birkaçı.

Soyut bir sınıf, çalışmanız için kısmen somut bir temele sahip olmanıza izin verir, bu bir arayüzle aynı değildir, ancak şablon yöntem modelini kullanarak kısmi uygulama oluşturma yeteneği gibi kendi niteliklerine sahiptir.


En önemli şeyi ihmal ettiniz: Bir arabirim uygulamak, sınıfınızı, söz konusu kodun sınıfınız hakkında herhangi bir şey bilmesine gerek kalmadan, bu arabirimin uygulanmasına ihtiyaç duyan herhangi bir kod tarafından kullanılabilir hale getirir.
supercat

2

@ User2211290 yanıtının gerçek bir örneği olarak:

Her ikisi de Arrayve Listarayüze sahip IList. Aşağıda a string[]ve a var List<string>ve her ikisini de IList kullanarak tek bir yöntemle kontrol ediyoruz :

string[] col1 = { "zero", "one", "two", "three", "four"};
List<string> col2 = new List<string>{ "zero", "one", "two", "three"};

//a methode that manipulates both of our collections with IList
static void CheckForDigit(IList collection, string digit)
{
    Console.Write(collection.Contains(digit));
    Console.Write("----");
    Console.WriteLine(collection.ToString()); //writes the type of collection
}

static void Main()
{
    CheckForDigit(col1, "one");   //True----System.String[]
    CheckForDigit(col2, "one");   //True----System.Collections.Generic.List`1[System.String]



//Another test:

    CheckForDigit(col1, "four");   //True----System.String[]
    CheckForDigit(col2, "four");   //false----System.Collections.Generic.List`1[System.String]
}

1

Yalnızca bir soyut sınıftan miras alabilirsiniz. Birden fazla arayüzden miras alabilirsiniz. Bu, çoğu durumda ne kullandığımı belirler.

Soyut sınıfın avantajı, temel bir uygulamaya sahip olabilmenizdir. Bununla birlikte, IDisposable durumunda, varsayılan bir uygulama işe yaramaz, çünkü temel sınıf şeyleri nasıl düzgün bir şekilde temizleyeceğini bilmiyor. Bu nedenle, bir arayüz daha uygun olacaktır.


1

Hem soyut sınıf hem de arayüz sözleşmelerdir.

Bir sözleşme fikri, bazı davranışları belirlemektir. Eğer uyguladığınızı söylerseniz, sözleşmeyi kabul etmişsinizdir.

Arayüz yerine soyut seçimi.

Soyut sınıfın herhangi bir soyut olmayan nesli sözleşmeyi uygulayacaktır.

karşı

Arayüzü uygulayan herhangi bir sınıf sözleşmeyi uygulayacaktır.

Bu nedenle, bazı davranışları belirtmek istediğinizde soyut kullanırsınız, tüm nesiller ayrı bir arayüz tanımlayarak kendinizi uygulamalı ve kurtarmalıdır, ancak şimdi bu etkin bir şekilde toplanmış sözleşmeyi karşılayan her şey bir alt bileşen olmalıdır.


1

Arayüzler, gerçekliğin (nesnelerin) soyutlamasının (sınıfların) bir soyutlamasını (bir arketip) yapmaktır.

Arayüzler, sınıflar tarafından sağlanan uygulamaları sağlamadan sözleşme koşullarını belirtmek içindir.

Arayüzler özelliklerdir:

  • Arayüzler, konseptin hareketsiz davranışını tek başına ve statik olduğu için belirleyen tasarım zamanı yapılarıdır.

  • Sınıflar, etkileşim ve hareket halindeki gerçekliğin mobil yapısını belirleyen uygulama zamanı yapılarıdır.

Arayüz nedir?

Bir kediyi gözlemlediğinizde onun dört pençesi, başı, gövdesi, kuyruğu ve kılı olan bir hayvan olduğunu söyleyebilirsiniz. Onun yürüyebildiğini, koşabildiğini, yemek yiyebildiğini ve miyavlayabildiğini görebilirsiniz. Ve bunun gibi.

Özellikleri ve işlemleriyle bir arayüz tanımladınız. Bu nedenle, herhangi bir çalışma şekli tanımlamadınız, sadece işlerin nasıl çalıştığını bilmeden sadece özellikler ve yetenekler tanımladınız: yetenekleri ve farklılıkları tanımladınız.

Bu nedenle, UML'de bunu bir sınıf diyagramında bir sınıf olarak adlandırmamıza rağmen, henüz bir sınıf değil, çünkü yapının derinlemesine bir görüşüne sahip olmaya başlamak için özel ve korumalı üyeleri tanımlayabiliriz. Burada kafanızı karıştırmayın çünkü UML'de bir arayüz, C #'daki bir arayüzden biraz farklıdır: soyutlama atomuna kısmi bir erişim noktası gibidir. Bu nedenle, bir sınıfın birden fazla arabirim uygulayabileceğini söyledik. Bu nedenle, aynı şeydir, ancak değildir, çünkü C # 'daki arayüzler hem soyutlamayı soyutlamak hem de bu soyutlamayı bir erişim noktası olarak sınırlamak için kullanılır. İki farklı kullanım alanı. Bu nedenle, UML'deki bir sınıf, bir programlama sınıfına tam bir bağlantı arayüzünü temsil ederken, bir UML arayüzü, bir programlama sınıfının bir bölümünün bir ayrıştırma arayüzünü temsil eder. Aslında, UML'deki sınıf diyagramı uygulama ile ilgilenmez ve tüm yapıtları programlama arayüzü seviyesindedir. UML sınıflarını programlama sınıflarıyla eşlerken, soyut soyutlamanın somut soyutlamaya aktarılmasıdır. Tasarım alanı ile programlama alanı arasındaki ikilemi açıklayan bir incelik var. Dolayısıyla, UML'deki bir sınıf, iç gizli şeyleri göz önünde bulundurarak bir programlama arayüzü açısından bir programlama sınıfıdır.

Arayüzler ayrıca, garip bir şekilde kullanılamadığında çoklu kalıtımı simüle etmeye de izin verir. Örneğin, cat sınıfı, kendisini hayvan arayüzünden türeten cat arayüzünü uygulayacaktır. Bu cat sınıfı aynı zamanda şu arayüzleri de uygulayacaktır: yürüyün, koşun, yemek yiyin ve ses çıkartın. Bu, sınıf düzeyinde çoklu mirasın yokluğunu telafi eder, ancak her seferinde her şeyi yeniden uygulamanız gerekir ve gerçekliği en iyi durumda gerçekliğin yaptığı gibi hesaba katamazsınız.

Arayüzü ve uygulama bölümlerini bir birimde tanımladığınız Pascal Nesnesi kodlamasına başvurabileceğimizi anlamak için. Arayüzde türleri tanımlarsınız ve uygulamada türü uygularsınız:

unit UnitName;

interface

type
  TheClass = class
  public
    procedure TheMethod;
  end;

implementation

class procedure TheClass.TheMethod;
begin
end;

Burada, arayüz bölümü UML sınıf tasarımıyla eşleşirken, Arayüz türleri bu nedenle başka şeylerdir.

Yani bizim işimizde tek bir kelimemiz var, arayüz , iki farklı ama benzer şeyi belirtmek için ve bu bir kafa karışıklığı kaynağı.

Ayrıca C # 'da, örneğin, programlama arayüzleri, açık türlerde gerçek genel çok biçimliliğin yokluğunu, hedefi gerçekten başarmadan telafi etmeye izin verir, çünkü güçlü bir şekilde yazılmış hability'yi kaybettiniz.

Sonuçta, uyumsuz sistemlerin (Dağıtılmış) Ortak Nesne Modeli ile tanıtıldığı gibi bellekteki nesnelerin uygulanması ve yönetimi hakkında endişelenmeden iletişim kurmasına izin vermek için arabirimler gereklidir.

Sınıf nedir?

Dışsal bir bakış açısından gerçeklikte bir indirgeme tanımladıktan sonra, bunu içeriden bir perspektiften tanımlayabilirsiniz: Bu, kapsüllediğiniz gerçekliğin hayata geçmesine ve etkileşime girmesine izin vermek için veri işleme ve mesaj yönetimini tanımladığınız sınıftır. örnekleri kullanarak nesnelere.

Böylece, UML'de, makinenin tekerleklerinde fraktal bir daldırma fark edersiniz ve işlemek istediğiniz gerçeklik parçasının soyutlamasını uygulayabilmek için durumları, etkileşimleri vb. Tanımlarsınız.

Bu nedenle, soyut bir sınıf, derleyicinin bakış açısından bir şekilde bir arayüzün eşdeğeridir.

Daha fazla bilgi

Protokol (nesne yönelimli programlama)

C # - Arayüzler

C # - Sınıflar


1

Size uçan tost makinelerinden bahsedeyim.

tost makinesi

Elbette, herhangi bir arabirim bildirmeden veya uygulamadan çalışan bir yazılım sistemi kurabileceğiniz birçok durum vardır: herhangi bir nesneye yönelik yazılım tasarımı, sınıflardan başka hiçbir şey kullanılmadan gerçekleştirilebilir.

Sonra tekrar, herhangi bir yazılım sistemi Assembly Dili'nde veya daha iyisi Makine Kodu'nda uygulanabilir. Soyutlama mekanizmalarını kullanmamızın nedeni, işleri kolaylaştırma eğiliminde olmalarıdır. Arayüzler böyle bir soyutlama mekanizmasıdır.

Dolayısıyla, arayüzleri kullanırsanız uygulaması çok daha kolay olan ve bu durumlarda arayüzler pratik olarak gerekli hale gelen, bazı önemsiz olmayan nesne yönelimli tasarımlar vardır.

Bu önemsiz olmayan tasarımlar, "gerçek" biçiminde, bir sınıfın yalnızca bir temel sınıftan değil, iki veya daha fazla temel sınıftan miras aldığı çoklu kalıtımla ilgilidir. Bu gerçek biçim C # 'da mümkün değildir, ancak C # ve Java gibi diller ortaya çıkmadan önce, yönetilen dil, gerçek çoklu kalıtımı tam olarak destekleyen C ++ idi. Ne yazık ki, gerçek çoklu kalıtımın pek iyi bir fikir olmadığı ortaya çıktı, çünkü dilin tasarımını son derece karmaşıklaştırıyor ve aynı zamanda ünlü "Elmas Problemi" gibi çeşitli sorunlara da yol açıyor. ( J Francis'in "Çoklu kalıtımla ilgili kesin sorun nedir?" Cevabına bakın )

Yani, eğer birisi bir "uçan ekmek kızartma makinesi" sınıfı inşa etmek isterse, mevcut bir "ekmek kızartma makinesi" sınıfından ve ayrıca mevcut bazı "uçan" sınıftan miras alırdı. Muhtemelen karşılaşacakları türden bir sorun, ekmek kızartma makinesi sınıfının güç kaynağının bir duvar prizi olması, uçan makine sınıfının güç kaynağının muhtemelen güvercin yiyeceği olmasıydı ve ortaya çıkan yeni sınıf ya her nasılsa ikisine birden sahip olursanız, hangisine sahip olacağı belli olmazdı. (Elmas Sorunu.)

C # ve Java gibi dillerin yaratıcıları, dili basit tutmak ve Elmas Problemi gibi tuzaklardan kaçınmak için gerçek çoklu kalıtıma izin vermemeye karar verdiler. Bununla birlikte, bazı tür çoklu kalıtım hala gereklidir (veya en azından çok arzu edilir), bu nedenle bu dillerde, sorunlardan ve gerçek çoklu kalıtımın karmaşıklığından kaçınırken daha küçük bir çoklu kalıtım biçimini desteklemek için bir araç olarak arayüzler sundular.

Bu daha küçük çoklu miras biçiminde, birden fazla temel sınıftan miras alan bir sınıfa sahip olmanıza izin verilmez, ancak en azından bir veya daha fazla arabirimden miras alabilirsiniz. Yani, bir uçan ekmek kızartma makinesi inşa etmek istiyorsanız, hem mevcut bir ekmek kızartma makinesi sınıfından hem de mevcut bir uçan sınıftan miras alamazsınız, ancak yapabileceğiniz şey, mevcut bir ekmek kızartma makinesi sınıfından miras almak ve ardından kendi uyguladığınız bir uçan arayüzü ortaya çıkarmaktır. muhtemelen ekmek kızartma makinesinden miras aldığınız araçları kullanarak.

Bu nedenle, iki farklı ve ilgisiz işlevsellik kümesini bir araya getiren bir sınıf yaratma ihtiyacı hissetmedikçe, herhangi bir çoklu kalıtım biçimine ihtiyacınız olmayacak, bu nedenle herhangi bir arabirim bildirmeniz veya uygulamanız gerekmeyecek.


0

Arayüzler, sınıf tasarımcısının mevcut yöntemleri son kullanıcı için çok açık hale getirmesine izin verir. Aynı zamanda polimorfizmin ayrılmaz bir parçasıdır.


İlk ifadenizde iyi söylediniz. Ama 2. cümlenizi anlamıyorum, lütfen gerçek zamanlı bir örnekle detaylandırır mısınız?
Öğrenci

0

Arayüzün tanımını soyut bir sınıfa göndermeyeceğim çünkü teoriyi çok iyi bildiğinizi düşünüyorum ve SOLID ilkelerini bildiğinizi varsayıyorum, bu yüzden pratik yapalım.

Bildiğiniz gibi arayüzler herhangi bir koda sahip olamaz, bu yüzden dezavantajı anlamak oldukça basittir.

Bir kurucu sağlayan sınıfınızın özelliğini başlatmanız gerekiyorsa veya uygulamanın bir bölümünü sağlamak istiyorsanız, soyut bir sınıf, bunu yapmanıza izin vermeyecek bir arayüze iyi bir uyum sağlayacaktır.

Bu nedenle, çok genel olarak, istemciye sınıfınızı devralacak / genişletecek bir kurucu veya herhangi bir kod sağlamanız gerektiğinde, arayüzlere soyut sınıfı tercih etmelisiniz.


-2

Soyut sınıf, Interfaces'in ilgisiz varlıklar için kullanılabildiği ilgili varlıklar için oluşturulur.

Örneğin, Hayvan ve İnsan diyen iki varlığım varsa o zaman Arayüz'e gideceğim ve sanki ayrıntılı olarak gitmek zorundayım diyelim Kaplan, aslan ve Hayvan ile ilişki kurmak istiyorum, sonra Hayvan Soyut sınıfını seçeceğim ..

aşağıdaki gibi görünecek

   Interface             
   ____|____
  |        |
Animal   Human



  Animal (Abstract class)
   __|___
  |      |
Tiger   Lion
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.