Класс PtSalesPerson представляет продавца, который работает на условиях частичной занятости. В качестве варианта скажем, что нужно гарантировать отсутствие возможности создания подкласса PtSalesPerson. Чтобы предотвратить наследование от класса, необходимо применить ключевое слово sealed:
sealed class PtSalesPerson : SalesPerson
{
public PtSalesPerson(string fullName, int age, int empId,
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;
}
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
}
}
// 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;
}
}
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
}
Обратите внимание, что между примерами использования типов записей и предшествующими примерами применения классов нет большой разницы. Модификатор доступа 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);
}