Как упоминалось ранее, в версии C# 8.0 методы и свойства интерфейса могут иметь стандартные реализации. Добавьте к проекту новый интерфейс по имени IRegularPointy
namespace CustomInterfaces
{
interface IRegularPointy : IPointy
{
int SideLength { get; set; }
int NumberOfSides { get; set; }
int Perimeter => SideLength * NumberOfSides;
}
}
Добавьте к проекту новый файл класса по имени Square.cs
Shape и реализуйте интерфейс IRegularPointy:namespace CustomInterfaces
{
class Square: Shape,IRegularPointy
{
public Square { }
public Square(string name) : base(name) { }
// Метод Draw поступает из базового класса Shape
public override void Draw
{
Console.WriteLine("Drawing a square");
}
// Это свойство поступает из интерфейса IPointy
public byte Points => 4;
// Это свойство поступает из интерфейса IRegularPointy.
public int SideLength { get; set; }
public int NumberOfSides { get; set; }
// Обратите внимание, что свойство Perimeter не реализовано.
}
}
Здесь мы невольно попали в первую "ловушку", связанную с использованием стандартных реализаций интерфейсов. Свойство Perimeter
IRegularPointy, в классе Square не определено, что делает его недоступным экземпляру класса Square. Чтобы удостовериться в этом, создайте новый экземпляр класса Square и выведите на консоль соответствующие значения:Console.WriteLine("\n***** Fun with Interfaces *****\n");
...
var sq = new Square("Boxy")
{NumberOfSides = 4, SideLength = 4};
sq.Draw;
// Следующий код не скомпилируется:
// Console.WriteLine($"{sq.PetName} has {sq.NumberOfSides} of length
{sq.SideLength} and a
perimeter of {sq.Perimeter}");Взамен экземпляр Square
IRegularPointy (т.к. реализация находится именно там) и тогда можно будет получать доступ к свойству Perimeter. Модифицируйте код следующим образом:Console.WriteLine($"{sq.PetName} has {sq.NumberOfSides} of length {sq.SideLength} and a
perimeter of {((IRegularPointy)sq).Perimeter}");
Один из способов обхода этой проблемы — всегда указывать интерфейс типа. Измените определение экземпляра Square
Square тип IRegularPointy:IRegularPointy sq = new Square("Boxy") {NumberOfSides = 4, SideLength = 4};
Проблема с таким подходом (в данном случае) связана с тем, что метод Draw
PetName в интерфейсе не определены, а потому на этапе компиляции возникнут ошибки.Хотя пример тривиален, он демонстрирует одну из проблем, касающихся стандартных реализаций. Прежде чем задействовать это средство в своем коде, обязательно оцените последствия того, что вызывающему коду должно быть известно, где находятся реализации.
Статические конструкторы и члены (нововведение в версии 8.0)
Еще одним дополнением интерфейсов в C# 8.0 является возможность наличия в них статических конструкторов и членов, которые функционируют аналогично статическим членам в определениях классов, но определены в интерфейсах. Добавьте к интерфейсу IRegularPointy
interface IRegularPointy : IPointy
{
int SideLength { get; set; }
int NumberOfSides { get; set; }
int Perimeter => SideLength * NumberOfSides;
// Статические члены также разрешены в версии C# 8
static string ExampleProperty { get; set; }
static IRegularPointy => ExampleProperty = "Foo";
}
Бьёрн Страуструп , Ирина Сергеевна Козлова , Бьерн Страуструп , Валерий Федорович Альмухаметов
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT