Интерфейс C# и базовые классы

У меня есть C интерфейс#, и конкретный класс, который реализует этот интерфейс. Теперь я хочу создать другой класс, который реализует этот интерфейс. Все очень просто.

однако большинство методов будут точно такими же в классах, и только несколько методов фактически изменятся.

Я не хочу дублировать всю логику в моем 2-м классе, которая содержится в моем первом.

Как создать 2-й класс и использовать логику в моем первом классе, кроме за лишние вещи?

мой интерфейс называется IEventRepository, а мой 1-й класс называется BaseEvents. Теперь я хочу создать новый класс под названием FooBarEvents.

мое определение класса для FooBarEvents:

public class FooBarEvents : BaseEvents, IEventRepository

мое намерение состояло в том, чтобы затем использовать базу возврата.Метод () в каждом методе, который дублирует код.

Я предполагаю, что это не правильно?

8 ответов


FooBarEvents нужно только наследовать от BaseEvents, также не реализовать IEventRepository, as BaseEvents уже реализует интерфейс. Если вам нужно изменить поведение некоторых IEventRepository методы FooBarEvents, просто переопределить эти методы.

Edit: некоторые примеры

interface IEventRepository
{
   void CommonMethodA();
   void CommonMethodB();
   void ImplentationSpecificMethod();
}

abstract class BaseEvents : IEventRepository
{
   public void CommonMethodA()
   { ... }

   public virtual void CommonMethodB()
   { ... }

   public abstract void ImplementationSpecificMethod();

   public void BaseEventsMethod()
   { ... }

   public void BaseEventsMethod2()
   { ... }
}

class FooBarEvents : BaseEvents
{
   public override void CommonMethodB()
   { 
      // now FooBarEvents has a different implementation of this method than BaseEvents
   }

   public override void ImplementationSpecificMethod()
   { 
      // this must be implemented
   }

   public new void BaseEventsMethod2()
   { 
      // this hides the implementation that BaseEvents uses
   }

   public void FooBarEventsMethod()
   { 
      // no overriding necessary
   }
}

// all valid calls, assuming myFooBarEvents is instantiated correctly
myFooBarEvents.CommonMethodA()
myFooBarEvents.CommonMethodB()
myFooBarEvents.BaseEventsMethod();
myFooBarEvents.BaseEventsMethod2();
myFooBarEvents.FooBarEventsMethod();
myFooBarEvents.ImplementationSpecificMethod();

// use the contract thusly:
void DoSomethingWithAnEventRepository(BaseEvents events)
{ ... }

С BaseEvents уже реализует IEventRepository, вам не нужно реализовывать его снова в FooBarEvents. FooBarEvents автоматически наследует '.


почему бы вам не задать ваши методы в базовом классе как Virtual и переопределить те, которые вы хотите изменить в классе ребенка?


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

public interface IEventRepository
{
  void Method1();
  void Method2();
}

public abstract class BaseEvents : IEventRepository
{
  public void Method1() 
  {
    Console.WriteLine("This is shared functionality");
  }

  public abstract void Method2();
}

public class Implementation1 : BaseEvents
{
  override public void Method2()
  {
    Console.WriteLine("Impl1.Method2");
  }
}

public class Implementation2 : BaseEvents
{
  override public void Method2()
  {
    Console.WriteLine("Impl2.Method2");
  }
}

public class Program
{
  static void Main(string[] args)
  {
    var implementations = new List<IEventRepository> { new Implementation1(), new Implementation2() };

    foreach (var i in implementations) 
    {
       Console.WriteLine(i.GetType().Name);
       Console.Write("\t");
       i.Method1();  // writes 'This is shared functionality'

       Console.Write("\t");
       i.Method2(); // writes type specific message
    }
  }

}


вы можете сделать свой второй класс расширить свой первый класс. Ваш первый класс может быть абстрактным, но реализовывать только общие методы из интерфейса.


использовать наследование:

public interface IFoo
{
    void GeneralBehaviorMethod1();
    void GeneralBehaviorMethod2();
    void SpecificBehaviorMethod1();
}

public class Bar: IFoo
{
     public void GeneralBehaviorMethod1() {...}
     public void GeneralBehaviorMethod2() {...}

     public virtual void SpecificBehaviorMethod1() {...}
     ...
}

public class BarOnSteroids: Bar
{
    public override void SpecificBehaviorMethod1() {...}
}

BarOnSteroids наследует все поведение Bar и вы можете изменить конкретное поведение любых методов, которые вам нужны, переопределив их в BarOnSteroids (они должны быть помечены как виртуальные в базовом классе Bar).

таким образом, у вас будет следующее:

IFoo iFoo = new Bar();
iFoo.SpecificBehaviorMethod1(); //Bar implementation will be called;

IFoo iFoo = new BarOnSteroids();
iFoo.SpecificBehaviorMethod1(); //BarOnSteroids implementation will be called.
iFoo.CommonBehaviorMethod1(); //Bar implementation will be called.

Bar bar = new BarOnSteroids();
bar.SpecificBehaviorMethod1(); //BarOnSteroids implementation will be called.
bar.CommonBehaviorMethod1(); //Bar implementation will be called.

это предполагает, что вы хотите изменить поведение методов, которые являются частью IFoo интерфейс. Если все, что вы хотите, это добавить дополнительные функции к BarOnSteroids тогда просто наследовать форму Bar наследовать все это функциональность и добавить все необходимые новые методы для реализации новой функциональности.


если определенный выбор методов BaseEvents реализация IEventRepository are всегда собирается поддерживать ту же реализацию, то вы можете просто реализовать их в BaseEvents класс и отметьте те, которые может изменить как virtual. Таким образом, если FooBarEvents желает изменить реализацию одного из методов, его можно просто переопределить его.

просто Примечание относительно добавления IEventsRepository на FooBarEvents class: это действительно сделать. Видеть здесь для ответа Джона Скита об этом.


есть несколько разных подходов.

один. Полностью пропустите интерфейс и сделайте его абстрактным классом. Это проще, когда он работает, но то, что вы можете иметь только один базовый класс ограничивает использование в C#

public abstract class EventRepository
{
  public abstract int MustBeOverridden(string str);//classes have to override this
  public virtual int CanBeOverridden(int i)//classes can override but may choose not to.
  {
    return 4;
  }
  public int CannotOverride(string str)//this is always the same
  {
    return MustBeOverridden(str) + 3;//can make use of this
  }
}

вы можете иметь один класс, реализующий интерфейс, и другой производный от него:

public interface IEventRepository
{
  int Method1(string str);
  int Method2(string str);
}

public class EventClass1 : IEventRepository
{
  public int Method1(string str)//can't be overridden as not marked virtual
  {
    return 1;
  }
  public virtual int Method2(string str)//can be overridden
  {
    return 2;
  }
}

public class EventClass2 : EventClass1
{
  public override int Method2(string str)
  {
    return -2;
  }
}

пусть они оба переопределяют абстрактный класс, который дает некоторое общее поведение:

public abstract class EventClass : IEventRepository
{
  public abstract int Method1(string str);
  public int Method2(string str)
  {
    return 2;
  }
}

public class EventClass1 : EventClass
{
  public override int Method1(string str)
  {
    return 1;
  }
}
public class EventClass2 : EventClass
{
  public override int Method1(string str)
  {
    return -1;
  }
}

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

будьте осторожны, хотя этот шаблон:

public class EventClass1 : IEventRepository
{
  public int Method1(string str)//not override-able
  {
    return 1;
  }
  public int Method2(string str)//not override-able
  {
    return 2;
  }
}
public class EventClass2 : EventClass1, IEventRepository
{
  //We really want our own Method1!
  public new int Method1(string str)
  {
    return 3;
  }
  int IEventRepository.Method1(string str)
  {
    return -1;
  }
}

EventClass2 e2 = new EventClass2();
EventClass1 e1 = e2;
IEventRepository ie = e2;
Console.WriteLine(e2.Method1(null));//3
Console.WriteLine(e1.Method1(null));//1
Console.WriteLine(ie.Method1(null));//-1

, даже если IEventRepository.Method1 определяется более разумно, выше, вероятно, приведет к путанице.