Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

float currPay, string ssn, int numbOfSales)

: base(fullName, age, empId, currPay, ssn, numbOfSales)

{

}

// Остальные члены класса...

}

Наследование с типами записей (нововведение в версии 9.0)

Появившиеся в версии C# 9.0 типы записей также поддерживают наследование. Чтобы выяснить как, отложите пока свою работу над проектом

Employees
и создайте новый проект консольного приложения по имени
RecordInheritance
. Добавьте в него два файла
с именами
Car.cs
и
MiniVan.cs
, содержащими следующие определения записей:

// Car.cs

namespace RecordInheritance

{

//Car record type

public record Car

{

public string Make { get; init; }

public string Model { get; init; }

public string Color { get; init; }

public Car(string make, string model, string color)

{

Make = make;

Model = model;

Color = color;

}

}

}

// MiniVan.cs

namespace RecordInheritance

{

//MiniVan record type

public sealed record MiniVan : Car

{

public int Seating { get; init; }

public MiniVan(string make, string model, string color, int seating)

: base(make,
model, color)

{

Seating = seating;

}

}

}

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

protected
для свойств и методов ведет себя аналогично, а модификатор доступа
sealed
для типа записи запрещает другим типам записей быть производными от запечатанных типов записей. Вы также обнаружите работу с унаследованными типами записей в оставшихся разделах главы. Причина в том, что типы записей — это всего лишь особый вид неизменяемого класса (как объяснялось в главе 5). Вдобавок типы записей включают неявные приведения к своим базовым классам, что демонстрируется в коде ниже:

using System;

using RecordInheritance;

Console.WriteLine("Record type inheritance!");

Car c = new Car("Honda","Pilot","Blue");

MiniVan m = new MiniVan("Honda", "Pilot", "Blue",10);

Console.WriteLine($"Checking MiniVan is-a Car:{m is Car}");

// Проверка, является ли MiniVan типом Car

Как и можно было ожидать, проверка того, что

m
является
Car
, возвращает
true
, как видно в следующем выводе:

Record type inheritance!

Checking minvan is-a car:True

Важно отметить, что

хотя типы записей представляют собой специализированные классы, вы не можете организовывать перекрестное наследование между классами и записями. Другими словами, классы нельзя наследовать от типов записей, а типы записей не допускается наследовать от классов. Взгляните на приведенный далее код; последние два примера не скомпилируются:

namespace RecordInheritance

{

public class TestClass { }

public record TestRecord { }

// Классы не могут быть унаследованы от записей

// public class Test2 : TestRecord { }

// Записи не могут быть унаследованы от классов

// public record Test2 : TestClass { }

}

Наследование также работает с позиционными типами записей. Создайте в своем проекте новый файл по имени

PositionalRecordTypes.cs
и поместите в него следующий код:

namespace RecordInheritance

{

public record PositionalCar (string Make, string Model, string Color);

public record PositionalMiniVan (string Make, string Model, string Color)

: PositionalCar(Make, Model, Color);

}

Добавьте к операторам верхнего уровня показанный ниже код, с помощью которого можно подтвердить то, что вам уже известно: позиционные типы записей работают точно так же, как типы записей.

PositionalCar pc = new PositionalCar("Honda", "Pilot", "Blue");

PositionalMiniVan pm = new PositionalMiniVan("Honda", "Pilot", "Blue", 10);

Console.WriteLine($"Checking PositionalMiniVan is-a PositionalCar:

{pm is PositionalCar}");

Эквивалентность с унаследованными типами записей

Вспомните из главы 5, что для определения эквивалентности типы записей используют семантику значений. Еще одна деталь относительно типов записей связана с тем, что тип записи является частью соображения, касающегося эквивалентности. Скажем, взгляните на следующие тривиальные примеры:

public record MotorCycle(string Make, string Model);

public record Scooter(string Make, string Model) : MotorCycle(Make,Model);

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

MotorCycle mc = new MotorCycle("Harley","Lowrider");

Scooter sc = new Scooter("Harley", "Lowrider");

Console.WriteLine($"MotorCycle and Scooter are equal: {Equals(mc,sc)}");

Вот вывод:

Record type inheritance!

MotorCycle and Scooter are equal: False

Реализация модели включения/делегации

Поделиться с друзьями: