День двести шестьдесят восьмой. #ЗаметкиНаПолях

Нетривиальный пример использования явной реализации интерфейса

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

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

Например, вы можете создать интерфейс IPrintable, который определяет методы, используемые для печати любого объекта. Это хорошая идея, потому что теперь у принтера можно попросить напечатать любой объект класса, реализующего IPrintable. Если подумать, то методы интерфейса IPrintable имеют смысл только тогда, когда они используются чем-то, пытающимся напечатать объект. Не имеет смысла вызывать методы печати в каком-либо ином контексте, кроме как через ссылку на IPrintable. Этого можно добиться, сделав реализацию методов печати явной, то есть добавив имя интерфейса к объявлению тела метода.

Следующий код показывает класс Report, который реализует интерфейс IPrintable. Класс Report содержит два метода: GetPrintableText и GetTitle, которые объявлены в интерфейсе IPrintable.

interface IPrintable

{

string GetPrintableText(int page);

string GetTitle();

}

class Report : IPrintable

{

string IPrintable.GetPrintableText(int page)

{

return "Текст отчёта";

}

string IPrintable.GetTitle()

{

return "Заголовок отчёта";

}

}

Теперь единственный способ получить доступ к этим методам в экземпляре отчёта – приведя отчёт к IPrintable. На рисунке ниже показан эффект в Visual Studio: методы GetPrintableText и GetTitle скрыты от IntelliSense, если обращаться через класс Report напрямую, но при обращении через IPrintable они видны.

Таким образом можно спрятать методы, не относящиеся непосредственно к функционалу класса. Потребители класса-отчёта (кроме принтера) не смогут использовать эти методы, т.к. они им не нужны. Более того, используя частичные (partial) классы, можно и сам код этих методов вынести в отдельный файл, чтобы он не загромождал код основного функционала.



Источник: Rob Miles “Exam Ref 70-483 Programming in C#”. 2nd ed - Pearson Education, Inc., 2019. Глава 2.