Чи може клас успадкувати від іншого класу та інтерфейс у C #?


130

Хочу знати, чи може клас успадкувати клас та інтерфейс. Приклад коду нижче не працює, але я думаю, він передає те, що я хочу зробити. Причиною цього я є те, що в моїй компанії ми виробляємо USB, серійні, Ethernet тощо пристрої. Я намагаюся розробити загальний компонент / інтерфейс, який я можу використовувати для написання програм для всіх наших пристроїв, які допоможуть зберегти загальні речі (наприклад, підключення, відключення, отримання прошивки) однаковими для всіх наших програм.

Щоб додати до цього питання: Якщо GenericDevice знаходиться в іншому проекті, чи можу я помістити інтерфейс IOurDevices в цей проект, а потім змусити клас USBDevice реалізувати інтерфейс, якщо я додаю посилання на перший проект? Тому що хотілося б просто посилатися на один проект, а потім реалізовувати різні інтерфейси залежно від того, що це за пристрій.

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
Для подальшої довідки в розділі 10.1.4 специфікації C # описано точно, як оголосити клас, який має кілька базових типів.
Ерік Ліпперт

@Eric Lippert: Чи можете ви, будь ласка, допомогти мені зрозуміти цю справу, чи це правильний шлях і чи буде він доступний у майбутньому?
Gul Md Ershad

Відповіді:


246

Так. Спробуйте:

class USBDevice : GenericDevice, IOurDevice

Примітка: Базовий клас повинен бути перед списком імен інтерфейсу.

Звичайно, вам все одно потрібно буде реалізувати всі учасники, які визначають інтерфейси. Однак якщо базовий клас містить член, який відповідає члену інтерфейсу, член базового класу може працювати як реалізація члена інтерфейсу, і вам не потрібно вручну реалізовувати його знову.


1
Так, це працює! Чому я не подумав про це! І до коментарів нижче. Дякую, що ви мене
зрозуміли

1
@ Джордан, також зауважте, що базовий клас та список успадкованих інтерфейсів відокремлюються комами після початкової двокрапки (приклад @ Мехрдада).
JMD

1
щоб трохи розширитись: якщо ваш базовий клас реалізує інтерфейс, то ваш похідний клас автоматично реалізує цей інтерфейс - навіть без нього USBDevice : IOurDevice. Додавання реалізації явно не впливає на базовий клас, але це може допомогти зробити акцент на інтерфейсі.
STW

1
@David, хоча ви не помиляєтесь, не термінологія заважала коду @ Jordan працювати. Це був неправильний синтаксис.
JMD

2
+1 також для очищення питання, яке я хотів би задати щодо однакових членів як у Базі, так і в Інтерфейсі.
Riegardt Steyn

21

Ні, не зовсім. Але він може успадкувати від класу і реалізувати один або кілька інтерфейсів.

Чітка термінологія важлива при обговоренні подібних понять. Однією з речей, на яку ви побачите, наприклад, написання Джона Скіта, як тут, так і друком, є те, що він завжди точний у тому, як він декламує речі.


8
Або Ерік Ліпперт, написання якого дуже точне.
Матіас

21

Не пов'язане з питанням (відповідь Мехрдада має змусити вас продовжуватись), і я сподіваюся, що це не сприймається як нітроподібна: класи не успадковують інтерфейси, вони реалізують їх.

.NET не підтримує багатонаступне успадкування, тому дотримання термінів прямо може допомогти у спілкуванні. Клас може успадкувати один надклас і може реалізувати стільки інтерфейсів, скільки бажає.


У відповідь на коментар Еріка ... У мене була дискусія з іншим розробником щодо того, чи інтерфейси "успадковують", "реалізовують", "вимагають" або "зближують" інтерфейси із заявою типу:

public interface ITwo : IOne

Технічна відповідь така, що ITwoуспадковується IOneз кількох причин:

  • Інтерфейси ніколи не мають реалізації, тому аргументують це ITwo реалізацією IOne - це неправильно
  • ITwoуспадковує IOneметоди, якщо вони MethodOne()існують, IOneто вони також доступні ITwo. тобто: ((ITwo)someObject).MethodOne())є дійсним, хоча ITwoпрямо не містить визначення дляMethodOne()
  • ... бо час виконання так говорить! typeof(IOne).IsAssignableFrom(typeof(ITwo))повертаєtrue

Ми нарешті погодились, що інтерфейси підтримують справжнє / повне успадкування. Відсутні функції спадкування (такі як переопрацювання, абстрактні / віртуальні аксесуари тощо) відсутні в інтерфейсах, а не в успадкуванні інтерфейсу. Це все ще не робить концепцію простою чи зрозумілою, але це допомагає зрозуміти, що насправді відбувається під капотом у світі Еріка :-)


3
Хоча, на жаль, інтерфейси успадковують інші інтерфейси. Я вважаю цей вибір слів невдалим, але ми до цього застрягли. Я вважаю за краще інтерфейси вимагати інших інтерфейсів. Тобто, коли ви говорите "інтерфейс IFoo: IBar", це означає, що "реалізатор IFoo також повинен реалізувати IBar".
Ерік Ліпперт

@Eric Я погоджуюся, що це незрозумілий термін, і дебатував його з колегою деякий час назад. Врешті-решт ми вирішили, що говорячи "ITwo успадковує IOne". Я оновлю свою відповідь з кількох невеликих причин (просто тому, що вони не помістяться чітко в коментарі).
STW

Впевнений; якщо ви визначаєте "A успадковує від B" як означає "члени B - всі члени A", то інтерфейси "успадковують" з базових інтерфейсів. Це розумне визначення. Але я вважаю за краще "успадкування" як суворіше не просто ділитися абстрактними, нереалізованими членами, а, скоріше, бути спадковими реалізаціями . Оскільки інтерфейси не мають реалізацій, мені здається, що інтерфейси дещо заважають думати про інтерфейси як про успадковане від чого-небудь. Це тонкий і дискусійний момент.
Ерік Ліпперт

Ще один термін, який мені подобається, - це "продовжити". Таким чином, ви можете прочитати "інтерфейс IFoo: IBar", що означає, що IFoo розширює вимоги IBar.
Jasonh

1
@Joan: ви праві, що класи реалізують (і не можуть успадкувати) інтерфейси. Ерік зазначає, що інтерфейси можуть успадковувати інші інтерфейси - що може бути важко засвоюваним, враховуючи, що інтерфейси є лише "специфікаціями", а не реалізаціями.
STW

1

Я знайшов відповідь на другу частину своїх запитань. Так, клас може реалізувати інтерфейс, який знаходиться в іншому класі до тих пір, поки інтерфейс оголошений як загальнодоступний.


Він не повинен бути публічним у всіх випадках. Просто доступний. Наприклад class ContainsAll { private interface INested { /* ... */ } private class MyExample : INested { /* ... */ } }, MyExampleклас реалізує вкладений приватний інтерфейс. В інших прикладах може бути вкладений інтерфейс (і клас, що містить) internal. Все залежить від того, хто їм повинен користуватися і турбуватися з ними.
Jeppe Stig Nielsen
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.