Интерфейс против множественного наследования в C#

У меня есть набор классов A и B оба имеют некоторые свойства. и еще один класс C, который имеет свои собственные свойства.

всякий раз, когда я создаю экземпляр класса C, я хочу получить доступ ко всем свойствам всех трех классов с помощью objClassC.

Как я могу достичь этого в C#?

Я сталкиваюсь с двумя проблемами: -

  1. Я не могу наследовать оба класса A, B в классе C (C# не поддерживает множественное наследование)
  2. если я использую Интерфейс вместо класса A, B (в интерфейсе мы не можем содержать поля)

7 ответов


почему бы вам не содержать экземпляр класса A и класса B внутри класса C. используйте состав

class C
{
//class C properties
public A objA{get;set;}
public B objeB{get;set;}
}

затем вы можете получить доступ к

C objc = new C();
objc.objA.Property1 = "something";
objc.objB.Property1 = "something from b";

проверить статью композиция против наследования

EDIT:

если я использую интерфейс вместо класса A, B (в интерфейсе мы не можем Содержит Поля)

ну, интерфейсы не могут содержать поля, если вы определяете один, вы получит ошибку компиляции. Но интерфейсы могут содержать свойства, за исключением того, что вы не можете указать спецификаторы доступа, так как все элементы интерфейса, считаются public. Вы можете определить свойства интерфейса " A " и " B " как:

public interface IA
{
     int Property1 { get; set; }
}


public interface IB
{
    int Property2 { get; set; }
}

затем вы можете реализовать их в классе C, например:

public class C : IA, IB
{
    public int Property1 { get; set; }
    public int Property2 { get; set; }
}

позже вы можете использовать их в качестве:

C objC = new C();
objC.Property1 = 0;
objC.Property1 = 0;

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

Interface A
{
   int PropA {get; set;}
}


Interface B
{
  int PropB {get; set;}
}

class C : A, B
{

}

/ / поместите это утверждение в некоторый метод

C c = new C();
c.PropA = 1;
c.PropB = 2;

интерфейсы не являются решением проблемы отсутствия множественного наследования. Они просто не делают то же самое. Самое близкое, что вы можете получить, - это сделать C подклассом A и иметь свойство типа B. Возможно, если вы скажете нам, что должны делать A, B и C, мы сможем дать ответ, который лучше соответствует вашим потребностям...


интерфейсы могут содержать свойства, т. е.:

public interface IFoo
{
    string Bar { get; set; }
}

public interface IAA
{
    string NameOfA { get; set; }
}
public class AA : IAA
{
    public string NameOfA{get;set;}
}

public interface IBB
{
    string NameOfB { get; set; }
}    
public class BB : IBB
{
    public string NameOfB{get;set;}
}

public class CC : IAA, IBB
{
    private IAA a;
    private IBB b;            

    public CC()
    {
        a = new AA{ NameOfA="a"};
        b = new BB{ NameOfB="b"};
    }

    public string NameOfA{
        get{
            return this.a.NameOfA;
           }
        set{
            this.a.NameOfA = value;
           }
    }

    public string NameOfB
    {
        get{
            return this.b.NameOfB;
        }
        set{
            this.b.NameOfB = value;
        }
    }
}

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

interface ISomeProperties
  {int prop1 {get;set;}; string prop2 {get; set;}}
interface IMoreProperties
  {string prop3 {get;set;}; double prop4 {get; set;}}
interface ICombinedProperties : ISomeProperties, IMoreProperties; 
  { }

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

следует отметить, однако, что есть несколько вещей, которые можно сделать с полями, которые нельзя сделать со свойствами. Например, в то время как поле может быть передано Interlocked.Increment свойство не может; пытается Interlocked.Increment свойство путем копирования его в переменную, вызывая Interlocked.Increment на этом, а затем копирование результата обратно в свойство может "работать" в некоторых случаях, но потерпит неудачу, если два потока попытаются сделать то же самое одновременно (это было бы возможно, например, для обоих потоков, чтобы прочитать значение 5, увеличить его до 6, а затем записать обратно 6, в то время как два потока вызывают Interlocked.Increment на поле, которое изначально было равно 5, будет гарантированно давать 7.).

чтобы обойти это, может потребоваться, чтобы интерфейс включал некоторые методы, которые либо выполняют блокированный метод на поле (например, можно иметь функцию, которая вызывает Interlocked.Increment на поле и возвращает результат) и / или включают функции, которые будут вызывать указанный делегат с полем как


рассмотрим, как свойства по-разному предоставляются клиенту при использовании наследования vice composition.

наследование:

    var myCclass = new Cclass;
    myClass.propertyA;
    myClass.propertyB;
    myClass.propertyC;
    // and so on

состав:

 var myCclass = new Cclass;
    myCclass.bClass.propertyB;
    myCclass.aClass.propertyA;
    myCclass.propertyC;

наследование дает более чистый API-хорошая вещь.

закон Деметры - более известный как принцип наименьшего знания. Вы можно обойти это, имея свойства Cclass, которые один за другим предоставляют / возвращают свойства Bclass & Aclass - и ваши ссылки Bclass & Aclass будут закрытыми или защищенными в Cclass. И Cclass имеет полный контроль над тем, что подвергается, а не зависит от A & B, чтобы не иметь публичных вещей, которые вы не подвергались воздействию.

Я согласен с @AlejoBrz, интерфейсы здесь не подходят.

Я также киваю ,чтобы " предпочесть композицию наследованию."Но это руководство, а не жесткое и быстрое правило.