Я пытаюсь выяснить простой способ компоновки интерфейсов без создания нового суб-интерфейса, поскольку интерфейсы имеют многомерные отношения.Как создавать интерфейсы без использования суб-интерфейса или явного класса
interface IAnimal {}
interface ISwimmingAnimal : IAnimal {}
interface IVertebrate : IAnimal {}
interface IMammal : IVertebrate
{
IMammal Process();
}
interface IInvertebrate : IAnimal {}
interface IMollusc : IInvertebrate
{
IMollusc Process(object data);
}
Таким образом, некоторые конкретные классы были бы
class Vertebrate : IVertebrate {}
class SwimmingInvertebrate : ISwimmingAnimal, IInvertebrate {}
class SwimmingMammal : ISwimmingAnimal, IMammal
{
IMammal Process();
}
без необходимости композиции интерфейса, таких как ISwimmingAnimalInvertebrate
или ISwimmingAnimalMammal
.
Все хорошо, пока я не нужно использовать класс/интерфейс, который будет содержать экземпляры некоторых compostioned типов (То, что я хочу в теории):
interface IAnimalsCollection
{
IEnumerable<IAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates
{IAnimal, IVertebrate} Vertebrate { get; }
IEnumerable<{IAnimal, IInvertebrate}> Invertebrates { get; }
void UpdateVertebrate({IAnimal, IVertebrate} vertebrate);
void UpdateInvertebrate({IAnimal, IInvertebrate} invertebrate, int index);
}
class SwimmingAnimalsCollection : IAnimalsCollection
{
public IEnumerable<ISwimmingAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates
public {ISwimmingAnimal, IMammal} Vertebrate { get; }
public IEnumerable<{ISwimmingAnimal, IMollusc}> Invertebrates { get; }
public void UpdateVertebrate({ISwimmingAnimal, IMammal} vertebrate);
public void UpdateInvertebrate({ISwimmingAnimal, IMollusc} invertebrate, int index);
}
Я попытался это
interface IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
where TAnimal : IAnimal
where TVertebrate : TAnimal, IVertebrate
where TInvertebrate : TAnimal, IInvertebrate
{
IEnumerable<IAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates
{IAnimal, IVertebrate} Vertebrate { get; }
IEnumerable<{IAnimal, IInvertebrate}> Invertebrates { get; }
void UpdateVertebrate(TVertebrate vertebrate);
void UpdateInvertebrate(TInvertebrate invertebrate, int index);
}
class SwimmingAnimalsCollection<TAnimal, TVertebrate, TInvertebrate> : AnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
where TAnimal : ISwimmingAnimal
where TVertebrate : TAnimal, IMammal
where TInvertebrate : TAnimal, IMollusc
{
public IEnumerable<TAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates
public TVertebrate Vertebrate { get; }
public IEnumerable<TInvertebrate> Invertebrates { get; }
public void UpdateVertebrate(TVertebrate vertebrate) {}
public void UpdateInvertebrate(TInvertebrate invertebrate, int index) {}
}
За исключением того, что я не могу найти способ создать экземпляр SwimmingAnimalsCollection
с помощью только интерфейсов, так как это была проблема, которую я пытался решить в первую очередь, и я не могу использовать реализации классов из-за IMammal
и IMollusc
, потенциально возвращающих весь в разных классах. Фактически, в реальной реализации есть пары классов, которые являются UnProcessedX
, которые возвратят класс ProcessedX
, который просто вернется, если вы попытаетесь обработать его дальше.
Так как я хотел бы сделать
collection.UpdateVertebrate((TVertebrate)collection.Vertebrate.Process())
и ProcessedVertebrate
не является UnProssesedVertebrate
.
я вижу примерно три пути решения этого:
- Я мог бы сломаться и создавать композиционные интерфейсы, убивающий любую простую инъекцию зависимостей .
- Я мог бы создать фиктивные абстрактные базовые классы (и надеюсь, что ничто не нуждается в цепочке глубокого наследования ), убивая любую возможность зависимости инъекции.
- Или я мог бы использовать компилятор C# с волшебной палочкой до тех пор, пока он не смягчится и не позволит создать композицию на месте.
Ключевое слово уже в вашем вопрос. Состав. Не наследование. https: //en.wikipedia.org/wiki/Composition_over_inheritance – CodeCaster
@CodeCaster Тогда я не уверен, что правильно объяснил. Мне не нужен класс, который может выполнять A, B и C, мне нужен класс, который может содержать экземпляры {IA, IB} и {IA IC} без определения промежуточных интерфейсов IAB и IAC. – Tory
Но все 'IB' и' IC' в вашем примере 'IA', почему вам нужно ограничивать оба? – InBetween