C # 'da, bir sınıf başka bir sınıftan ve bir arabirimden miras alabilir mi?


130

Bir sınıfın bir sınıftan ve bir arabirimden miras alıp alamayacağını bilmek istiyorum. Aşağıdaki örnek kod çalışmıyor, ancak yapmak istediğimi ifade ettiğini düşünüyorum. Bunu yapmak istememin sebebi firmamda USB, seri, ethernet vb cihazlar yapıyor olmamızdır. Tüm uygulamalarımız için ortak şeyleri (bağlanma, bağlantıyı kesme, aygıt yazılımı alma gibi) aynı tutmaya yardımcı olacak tüm cihazlarımız için programlar yazmak için kullanabileceğim genel bir bileşen / arayüz geliştirmeye çalışıyorum.

Bu soruya eklemek için: Eğer GenericDevice farklı bir projedeyse, IOurDevices arayüzünü o projeye koyabilir miyim, ardından ilk projeye bir referans eklersem USBDevice sınıfının arayüzü uygulamasını sağlayabilir miyim? Çünkü sadece bir projeye referans vermek ve ardından cihazın ne olduğuna bağlı olarak farklı arayüzler uygulamak istiyor.

class GenericDevice
{
   private string _connectionState;
   public connectionState
   {
      get{return _connectionState; }
      set{ _connectionState = value;}
   }
}

interface IOurDevices
{
   void connectToDevice();
   void DisconnectDevice();
   void GetFirmwareVersion();
}

class USBDevice : IOurDevices : GenericDevice
{
   //here I would define the methods in the interface
   //like this...
   void connectToDevice()
   {
       connectionState = "connected";
   }
}

//so that in my main program I can do this...

class myProgram
{
   main()
   {
      USBDevice myUSB = new USBDevice();
      myUSB.ConnectToDevice;
   }
}

5
İleride başvurmanız için, C # şartnamesinin 10.1.4 bölümü, birden çok temel türe sahip bir sınıfın nasıl bildirileceğini tam olarak açıklamaktadır.
Eric Lippert

@Eric Lippert: Lütfen bu vakanın doğru yol olup olmadığını ve gelecekte mevcut olup olmayacağını anlamama yardım eder misiniz?
Gul Md Ershad

Yanıtlar:


246

Evet. Deneyin:

class USBDevice : GenericDevice, IOurDevice

Not: Temel sınıf, arabirim adları listesinden önce gelmelidir.

Elbette, arayüzlerin tanımladığı tüm üyeleri uygulamanız gerekecektir. Ancak, temel sınıf bir arabirim üyesiyle eşleşen bir üye içeriyorsa, temel sınıf üyesi arabirim üyesinin uygulaması olarak çalışabilir ve bunu el ile yeniden uygulamanız gerekmez.


1
Evet, bu işe yarıyor! Neden bunu düşünmedim! Ve aşağıdaki yorumlara. Beni bu konuda açıkladığınız için teşekkür ederim (Sınıflar arayüzleri, UYGULAMA arayüzlerini miras
almaz

1
@Jordan, ayrıca temel sınıfın ve miras alınan arabirimler listesinin ilk iki noktadan sonra virgülle ayrıldığını unutmayın (@ Mehrdad örneği).
JMD

1
biraz genişletmek için: temel sınıfınız arabirimi uygularsa, türetilmiş sınıfınız bu arabirimi otomatik olarak uygular - olmadan bile USBDevice : IOurDevice. Uygulamanın açıkça eklenmesi temel sınıfı etkilemez, ancak arayüzün vurgulanmasına yardımcı olabilir.
STW

1
@David, yanılmıyorsun, @ Jordan'ın kodunun çalışmasını engelleyen terminoloji değildi. Yanlış sözdizimiydi.
JMD

2
Hem Üssün hem de Arayüzün özdeş üyeleriyle ilgili sormak istediğim bir soruyu temizlemek için +1.
Riegardt Steyn

21

Hayır, tam olarak değil. Ancak bir sınıftan miras alabilir ve bir veya daha fazla arabirim uygulayabilir .

Bunun gibi kavramları tartışırken açık bir terminoloji önemlidir. Göreceğiniz şeylerden biri, Jon Skeet'in, örneğin, hem burada hem de basılı olarak, her şeyi açıklama biçiminde her zaman kesin olmasıdır.


8
Veya yazımı çok doğru olan Eric Lippert.
Mathias

21

Sorusuna İlgisiz (Mehrdad cevabı gidiyorsun almalısınız) ve bu nitpicky olarak alınmaz umut: sınıflar yok devralır arayüzler, onlar uygulamak onları.

.NET çoklu devralmayı desteklemez, bu nedenle terimleri düz tutmak iletişimde yardımcı olabilir. Bir sınıf, bir üst sınıftan miras alabilir ve istediği kadar arabirim uygulayabilir.


Eric'in yorumuna yanıt olarak ... Başka bir geliştiriciyle, arayüzlerin aşağıdaki gibi bir bildirime sahip arayüzleri "miras alıp almayacağı", "uygulayıp uygulamayacağı", "gerektirip gerektirmeyeceği" veya "getirip getirmeyeceği" hakkında bir tartışma yaptım:

public interface ITwo : IOne

Teknik cevap, birkaç nedenden dolayı ITwomiras almasıdır IOne:

  • Arayüzlerin hiçbir zaman bir uygulaması yoktur, bu yüzden ITwo uygulamaları tartışmak tamamen IOneyanlıştır
  • ITwoIOneyöntemleri miras alır , eğer MethodOne()varsa, IOneo zaman da erişilebilirdir ITwo. yani: açıkça bir tanım içermese ((ITwo)someObject).MethodOne())bile geçerlidirITwoMethodOne()
  • ... çünkü çalışma zamanı öyle diyor! typeof(IOne).IsAssignableFrom(typeof(ITwo))İadelertrue

Nihayet arayüzlerin gerçek / tam mirası desteklediği konusunda anlaştık. Eksik kalıtım özellikleri (geçersiz kılmalar, soyut / sanal erişimciler vb.) Arabirim kalıtımından değil arabirimlerde eksiktir. Yine de kavramı basit ya da net yapmıyor, ancak Eric'in dünyasında kaputun altında gerçekten neler olup bittiğini anlamaya yardımcı oluyor :-)


3
Ne yazık ki arayüzler diğer arayüzleri devralır . Bu kelime seçimini talihsiz buluyorum, ama şimdi buna bağlıyız. Arayüzlerin başka arayüzler gerektirdiğini düşünmeyi tercih ederim . Yani, "arabirim IFoo: IBar" dediğinizde bu, "IBar'ı uygulamak için bir IFoo uygulayıcısı gereklidir" anlamına gelir.
Eric Lippert

@Eric Bunun belirsiz bir terim olduğunu kabul ediyorum ve bir süre önce bir meslektaşımla tartışmıştım. Sonunda "ITwo IOne'ı miras alır" demeye karar verdik. Cevabımı birkaç küçük sebeple güncelleyeceğim (sadece bir yoruma tam olarak uymadıkları için).
STW

Elbette; "A B'den miras alır" ifadesini "B'nin tüm üyeleri A'nın üyeleridir" anlamında tanımlarsanız, arayüzler temel arayüzlerden "miras alır". Bu makul bir tanımdır. Ama ben "kalıtımı" daha katı bir şekilde sadece soyut, uygulanmamış üyeleri paylaşmakla ilgili değil, uygulamaları miras almakla ilgili olarak düşünmeyi tercih ediyorum . Arayüzlerin uygulamaları olmadığı için, arayüzlerin herhangi bir şeyden miras aldığını düşünmek biraz rahatsız edici buluyorum. Bu ince ve tartışmalı bir nokta.
Eric Lippert

Sevdiğim bir diğer terim de "uzatma". Böylece IFoo'nun IBar'ın gereksinimlerini genişlettiği anlamına gelen "arabirim IFoo: IBar" ı okuyabilirsiniz.
jasonh

1
@Joan: Sınıfların arayüzleri uyguladığı (ve devralamayacağı) konusunda haklısınız . Eric'in vurguladığı nokta, arabirimlerin diğer arabirimleri miras alabilmesidir - bu, arabirimlerin uygulamalardan ziyade yalnızca "özellikler" olduğu düşünüldüğünde, sindirilmesi biraz zor olabilir.
STW

1

Sorularımın ikinci kısmının cevabını buldum. Evet, bir sınıf, arabirim genel olarak bildirildiği sürece farklı bir sınıfta bulunan bir arabirimi uygulayabilir.


Her durumda halka açık olmak zorunda değildir. Sadece erişilebilir. Örneğin class ContainsAll { private interface INested { /* ... */ } private class MyExample : INested { /* ... */ } }, MyExamplesınıf iç içe geçmiş bir özel arabirim uygular. Diğer örneklerde, yuvalanmış arabirim (ve içeren sınıf) olabilir internal. Her şey onları kimin kullanması gerektiğine ve onlarla uğraşmasına bağlı.
Jeppe Stig Nielsen
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.