Страницы

Поиск по вопросам

четверг, 13 декабря 2018 г.

Повторное использование кода и проблема множественного наследования в C#

Существует следующая структура приложения:

Реализация метода Id из интерфейса IGetId одинаковая везде. Но, исходя из этой структуры его нужно будет каждый раз переписывать в каждом классе, имплементирующего интерфейсы, порожденные от IGetId.
Если бы не было BaseModel это в принципе не было бы проблемой, т.к. можно было бы вынести реализацию этого метода в какой нибудь абстрактный класс AGetId и от него наследоваться, но множественное наследование не поддерживается, а композиция в данном случае нарушает целостность.
В PHP существует очень удобный инструмент - Trait. Он отлично решает данную проблему, но, к сожалению, в C# такого функционала нету.
В C# есть нечто похожее - extension methods, хоть это и совершенно разные вещи. Я пробовал сделать что-то с использованием методов расширения, но получилось на мой взгляд "не очень":
IGetId
public interface IGetId { int Id { get; } }
Extension methods
public static class CoreExtensions { public static int Id(this IGetId obj) { return obj.Id; } }
В любом случае, это не дало ожидаемого результата, мне по прежнем нужно реализовывать Id в каждом классе.
Существуют ли какие-то средства для решения данной проблемы?


Ответ

Я бы предложил такую иерархию наследования:
// библиотечные интерфейсы interface IGetId { int Id { get; } } interface IPerson : IGetId { string Name { get; } } interface IAddres : IGetId { string City { get; } }
// универсальный базовый класс class BaseModel { /* ... */ }
// вспомогательный класс abstract class BaseModelWithId : BaseModel, IGetId { int id; public int Id => id; }
// реальные классы class Person : BaseModelWithId, IPerson { public string Name { get; set; } }
Необходимость реализовывать IGetId в Person отпала.

Хотя в общем случае вы правы, trait'ов не хватает. Есть хорошие шансы, что они появятся в будущем C# 8.

Комментариев нет:

Отправить комментарий