Базовый класс 'object'
Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy — урок 23 из 70.
В C# каждый создаваемый вами класс автоматически наследуется от специального класса, называемого object. Даже если вы явно не указываете базовый класс, вашим конечным предком все равно остается object. Это означает, что каждый тип в C# имеет общий набор методов.
Класс object предоставляет несколько виртуальных методов, которые вы можете переопределить в своих собственных классах:
public class Person
{
public string Name { get; set; }
// Переопределение из object
public override string ToString()
{
return $"Person: {Name}";
}
public override bool Equals(object obj)
{
if (obj is Person other)
return Name == other.Name;
return false;
}
public override int GetHashCode()
{
return Name?.GetHashCode() ?? 0;
}
}Три наиболее часто переопределяемых метода — это ToString() для строкового представления, Equals() для сравнения объектов и GetHashCode() для коллекций на основе хеша. По умолчанию ToString() возвращает имя типа, а Equals() проверяет ссылочное равенство.
Поскольку всё наследуется от object, вы можете хранить любой тип в переменной object:
object item1 = new Person { Name = "Alice" };
object item2 = 42;
object item3 = "Hello";
Console.WriteLine(item1.ToString()); // Person: AliceЭтот универсальный базовый класс — это то, что делает возможными такие функции, как коллекции, содержащие смешанные типы, и именно поэтому каждый объект в C# имеет доступ к таким методам, как ToString() и GetType().
Задание
ЛегкоДавайте создадим систему сравнения книг, которая демонстрирует, как переопределение методов базового класса object придает вашим пользовательским типам осмысленное поведение для строкового представления и проверки на равенство.
Вы создадите два файла для организации своего кода:
Book.cs: Определите классBookв пространстве именLibrary. Ваша книга должна иметь свойстваTitle(string) иAuthor(string), а также конструктор, который устанавливает оба значения. Переопределите три ключевых метода, унаследованных отobject:ToString()должен возвращать"{Title} by {Author}"Equals(object obj)должен возвращатьtrue, если другой объект являетсяBookс тем жеTitleиAuthorGetHashCode()должен комбинировать хэш-коды обоих свойств
Program.cs: В основном файле создайте две книги, используя входные значения. Выведите каждую книгу с помощьюToString(), затем проверьте, равны ли они, и напечатайте результат. Наконец, продемонстрируйте, что вы можете сохранитьBookв переменной типаobjectи при этом получить осмысленный вывод при вызовеToString().
Вы получите четыре входных значения:
- Название первой книги
- Автор первой книги
- Название второй книги
- Автор второй книги
Выведите результат в следующем формате:
Book 1: {ToString result}
Book 2: {ToString result}
Are they equal? {True/False}
Stored as object: {ToString result of first book stored in object variable}Например, если входные данные — 1984, George Orwell, 1984 и George Orwell, вывод должен быть следующим:
Book 1: 1984 by George Orwell
Book 2: 1984 by George Orwell
Are they equal? True
Stored as object: 1984 by George OrwellЕсли входные данные — 1984, George Orwell, Brave New World и Aldous Huxley, вывод должен быть следующим:
Book 1: 1984 by George Orwell
Book 2: Brave New World by Aldous Huxley
Are they equal? False
Stored as object: 1984 by George OrwellОбратите внимание, как переопределенные методы придают объектам Book осмысленное поведение — они красиво отображаются в виде строк и могут сравниваться по их содержимому, а не только по ссылкам в памяти!
Шпаргалка
В C# каждый класс автоматически наследуется от класса object, который предоставляет несколько виртуальных методов, которые можно переопределить:
Общие методы Object для переопределения
ToString()- Возвращает строковое представление объекта (по умолчанию возвращает имя типа)Equals(object obj)- Сравнивает объекты на равенство (по умолчанию проверяет ссылочное равенство)GetHashCode()- Возвращает хэш-код для использования в хэш-коллекциях
Переопределение методов Object
public class Person
{
public string Name { get; set; }
// Переопределение ToString для пользовательского строкового представления
public override string ToString()
{
return $"Person: {Name}";
}
// Переопределение Equals для сравнения на основе содержимого
public override bool Equals(object obj)
{
if (obj is Person other)
return Name == other.Name;
return false;
}
// Переопределение GetHashCode для хэш-коллекций
public override int GetHashCode()
{
return Name?.GetHashCode() ?? 0;
}
}Универсальный базовый класс
Любой тип может быть сохранен в переменной object:
object item1 = new Person { Name = "Alice" };
object item2 = 42;
object item3 = "Hello";
Console.WriteLine(item1.ToString()); // Person: AliceЭто универсальное наследование позволяет создавать коллекции, содержащие смешанные типы, и гарантирует, что каждый объект имеет доступ к таким методам, как ToString() и GetType().
Попробуйте сами
using System;
using Library;
class Program
{
public static void Main(string[] args)
{
// Считать ввод для двух книг
string title1 = Console.ReadLine();
string author1 = Console.ReadLine();
string title2 = Console.ReadLine();
string author2 = Console.ReadLine();
// TODO: Создать два объекта Book, используя введенные значения
// TODO: Вывести Книгу 1, используя ToString()
// Формат: "Book 1: {ToString result}"
// TODO: Вывести Книгу 2, используя ToString()
// Формат: "Book 2: {ToString result}"
// TODO: Проверить, равны ли книги, и вывести результат
// Формат: "Are they equal? {True/False}"
// TODO: Сохранить первую книгу в переменную типа object и вывести ее
// Формат: "Stored as object: {ToString result}"
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыПространства имен и директивыВведение в классы и объектыКлючевое слово 'this'Методы и параметрыПоля и свойстваКонструкторыИнициализаторы объектовИтоги — Простой калькулятор4Наследование
Основы синтаксиса наследования (:)Ключевое слово 'base'Ключевые слова Virtual и OverrideЗапечатанные классыБазовый класс 'object'Итоги — Иерархия сотрудников7Продвинутые возможности
Перегрузка операторовИндексаторы (this[])Переопределение ToString()Методы расширенияПовторение — Пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПотокобезопасный SingletonПаттерн FactoryПаттерн Observer (События)Паттерн Strategy13Финальные испытания
Платформа для онлайн-обученияКомпонент игрового персонажаСервис аренды транспорта2Свойства и статические члены
Автоматически реализуемые свойстваСвойства только для чтения и записиСтатические поля и методыСтатические классыЧлены в виде выражений5Полиморфизм и интерфейсы
Полиморфизм: компиляция vs выполнениеИнтерфейс vs абстрактный классМножественные интерфейсыЯвные интерфейсыUpcasting и DowncastingИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция вместо наследованияGenerics (классы и методы)Делегаты и событияАтрибуты и рефлексияIDisposable и оператор usingОсновы Dependency Injection11Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн Компоновщик3Архитектура классов
Экземплярные и статические данныеКлючевые слова 'readonly' и 'const'Опорные поляПовторение — Менеджер банковских счетов6Инкапсуляция
Модификаторы доступаСвойства для инкапсуляцииРеализация скрытия данныхПаттерны неизменяемостиИтоги — Записи студентов9Переменное количество аргументов
Ключевое слово 'params'Необязательные параметрыИменованные аргументыПерегрузка методов