Г. Шилдт - Полный справочник по C# (1160789), страница 58
Текст из файла (страница 58)
Специально для подобных ситуаций в С# предусмрена возможность предотвращения наследования класса с помощью ключевого слова s e a l e d .Чтобы запретить наследование класса, предварите его объявление ключевым словом s e a l e d . Нетрудно догадаться, что нельзя объявлять класс одновременно с помощью двух модификаторов — a b s t r a c t и s e a l e d , поскольку абстрактный класс сам посебе "полуфабрикат" и его полная реализация возможна только в следующих"поколениях", т.е.
после создания производных классов.Рассмотрим пример sealed-класса.sealed class A {// Следующий класс создать невозможно.class В : А { // ОШИБКА! Класс А не может иметь наследников.Класс в не может быть производным от класса А, так как последний объявленsealed-классом.Класс o b j e c tВ С# определен специальный класс с именем o b j e c t , который является неявнымбазовым классом всех других классов и типов (включая типы значений).
Другими словами, все остальные типы выводятся из класса object. Это означает, что ссылочная переменная типа object может указывать на объект любого типа. Кроме того, посколькуС#-массивы реализованы как классы, переменная типа object также может ссылатьсяна любой массив. Строго говоря, С#-имя o b j e c t — еще одно имя для классаSystem.Object, который является частью библиотеки классов .NET Framework.Класс o b j e c t определяет методы, перечисленные в табл. 11.1. Эти методы доступны для каждого объекта.Таблица 11.1.
Методы класса objectНазначениеМетодpublic virtualpublicstaticbool Equals (objectob)bool Equals (o b j e c t obi,o b j e c t ob2)Глава 11. НаследованиеОпределяет, является ли вызывающий объест таким же, как обьект, адресуемый ссылкой obОпределяет, является ли объект оЫ таким же, как объект оЬ2313Окончание табл. 11.1МетодНмзначениеp r o t e c t e d F i n a l i z e ()Выполняет завершающие действия перед процессом сбора мусора. В С# метод F i n a l i z e () доступен через деструкторp u b l i c v i r t u a l i n t GetHashCode ()Возвращает хеш-код, связанный с вызывающим объектомp u b l i c Type GetTypeOПолучает тип объекта во время выполнения программыp r o t e c t e d obj e c tMemberwiseClone ()public s t a t i c boolReferenceEquals (object obi,object ob2)public v i r t u a l s t r i n g T o S t r i n g oВыполняет "поверхностное копирование" объекта, т.е.
копируются члены, но не объекты, на которые ссылаются эти членыОпределяет, ссылаются ли объекты оЫ и оЪ2 на один и тот жеобъектВозвращает строку, которая описывает объектНазначение некоторых из перечисленных выше методов требует дополнительныхразъяснений.
По умолчанию метод E q u a l s ( o b j e c t ) определяет, ссылаются ли вызывающий объект и объект, адресуемый аргументом, на один и тот же объект, т.е. методопределяет, являются ли эти две ссылки одинаковыми. Метод возвращает значениеt r u e , если объекты совпадают, и f a l s e — в противном случае. Этот метод можно переопределить в создаваемых им классах. Это позволит уточнить, что означает равенство для вашего класса. Например, вы можете так определить метод E q u a l s ( o b j e c t ) ,чтобы он сравнивал содержимое двух объектов (и давал ответ на вопрос, равны лиони).
Метод E q u a l s ( o b j e c t , o b j e c t ) для получения результата вызывает методEquals(object).Метод GetHashCode () возвращает хеш-код, связанный с вызывающим объектом.Этот хеш-код можно использовать с любым алгоритмом, который применяет хеширование как средство доступа к объектам, хранимым в памяти.Как упоминалось в главе 9, при перегрузке оператора "==" необходимо переопределить методы Equals ( o b j e c t ) и GetHashCode (), поскольку функции оператора"==" и метода Equals ( o b j e c t ) , как правило, должны быть идентичными. Переопределив метод Equals ( o b j e c t ) , необходимо переопределить и метод GetHashCode ( ) , .чтобы они были совместимы.Метод T o S t r i n g O возвращает строку, содержащую описание объекта, для которого вызывается этот метод. Кроме того, метод T o S t r i n g O автоматически вызывается при выводе объекта с помощью метода W r i t e L i n e ( ) .
Метод T o S t r i n g O переопределяется во многих классах, что позволяет подобрать описание специально для типов объектов, которые они создают. Вот пример:// Демонстрация использования метода T o S t r i n g O .u s i n g System;/class MyClass {static int count = 0 ;int id;public MyClass О {id = count;count++;}public override string ToStringO {return "Объект класса MyClass #" + id;314Часть I. Язык С#class Test {public static void Main() {MyClass obi = new MyClassO;MyClass ob2 = new MyClassO;MyClass ob3 = new MyClassO;Console.WriteLine(obi);Console.WriteLine(ob2);Console.WriteLine(ob3);Эта программаОбъект классаОбъект классаОбъект класса(генерирует следующие результаты:MyClass #0MyClass #1MyClass #2Приведение к объектному типу и восстановление значенияКак упоминалось выше, все С#-типы, включая типы значений, выведены из класса o b j e c t .
Следовательно, ссылку типа o b j e c t можно использовать в качестве ссылки на любой другой тип, включая типы значений. Если ссылку типа o b j e c t заставляют указывать на значение нессылочного типа, этот процесс называют приведением кобъектному типу (boxing). В результате этого процесса значение нессылочного типадолжно храниться подобно объекту, или экземпляру класса. Другими словами,"необъектное" значение помещается в объектную оболочку. Такой "необъектный"объект можно затем использовать подобно любому другому объекту, В любом случаеприведение к объектному типу происходит автоматически. Для этого достаточно присвоить значение ссылке на объект класса o b j e c t .
Все остальное доделает С#.Восстановление значения из "объектного образа" (unboxing) — это по сути процессизвлечения значения из объекта. Это действие выполняется с помощью операцииприведения типа, т.е. приведения ссылки на объект класса o b j e c t к значению желаемого типа.Рассмотрим простой пример, который иллюстрирует приведение значения к объектному типу и его восстановление.// Простой пример "объективизации" и "дезобъективизации".using System;class BoxingDemo {public s t a t i c void Main() {int x;object obj;x = 10;obj = x; // "Превращаем" х в объект.intу = (int)obj; // Обратное "превращение"// объекта obj в int-значение.Console.WriteLine(у);Глава 11.
Наследование315Эта программа отображает значение 10. Обратите внимание на то, что значениепеременной х приводится к объектному типу простым ее присваиванием переменнойobj, которая является ссылкой на объект типа o b j e c t . Целочисленное значение, хранимое в ссылочной переменной o b j , извлекается с помощью операции приведения ктипу i n t .А вот еще один (более интересный) пример приведения значения к объектномутипу.
На этот раз int-значение передается в качестве аргумента методу s q r ( ) , который использует параметр типа o b j e c t .// Приведение значений к объектному типу возможно// при передаче значений методам.using System;class BoxingDemo {public static void Main() {int x;x - 10;Console.WriteLine("Значение х равно: " + x ) ;// Це^е^е^ная х автоматически приводится/ / к объектному типу при передаче методу sqr().х = BoxingDemo.sqr(x);Console.WriteLine("Значение x в квадрате равно: " + х ) ;}static int sqr(object о) {return (int)о * (int)о;(При выполнении этой программы получаются такие результаты:Значение х равно: 10Значение х в квадрате равно: 100Здесь значение х при передаче методу s q r () автоматически приводится к объектному типу.Приведение к объектному типу и обратный процесс делает С#-систему типов полностью унифицированной.
Все типы выводятся из класса o b j e c t . Ссылке типаo b j e c t можно присвоить ссылку на любой тип. В процессе приведения значения кобъектному типу и его восстановления из объекта автоматически обрабатываются вседетали, соответствующие нессылочным типам. Более того, поскольку все типы выведены из класса o b j e c t , все они имеют доступ к методам этого класса. Рассмотрим,например, следующую маленькую, но удивительную программу.// "Объективизация" позволяет вызывать методы//класса o b j e c t для значений нессылочного типа!using System;class MethOnValue {public s t a t i c void Main() {Console.WriteLine(lO.ToString());}316Часть I.
Язык С#Эта программа отображает значение 10. Дело в том, что метод T o S t r i n g O возвращает строковое представление объекта, для которого он вызывается. В данном случае строковое представление числа 10 выглядит как 10!Использование класса object в качестве обобщенного типаданныхС учетом того, что o b j e c t — базовый класс для всех остальных С#-типов и чтоприведение значения к объектному типу и его восстановление из объекта происходятавтоматически, класс o b j e c t можно использовать в качестве обобщенного типа данных.
Например, рассмотрим следующую программу, которая создает массив объектовjcnacca o b j e c t , а затем присваивает его элементам данные различных типов.// Использование класса o b j e c t для создания// массива обобщенного типа.using System;class GenericDemo {public s t a t i c void Main() {object[] ga = new object[10];!// Сохраняем int-значения.f o r ( i n t i=0; l < 3; i++)ga[ij = i ;// Сохраняем double-значения.f o r ( i n t i=3; i < 6; i++)ga[i] = (double) i / 2;// Сохраняем две строки, bool- и char-значения,да[б] = "Массив обобщенного типа";да[7] = t r u e ;да[8] = f X'; 'да[9] = "Конец";f o r ( i n t i = 0; i < да.Length;Console.WriteLine("да[" + i + " ] : " + ga[i] + " " ) ;Вот результаты выполнения этой программы:да [0]: ОГ1 1 • 1да L-L J •2.
.да [23: 1.5да [3]:да [4]: 2да [5] : 2 . 5да [б]: Массив обобщенного типада [7]: Trueда[8]: Xда [9]: КонецКак видно по результатам выполнения программы, ссылку на объект классаo b j e c t можно использовать в качестве ссылки на данные других типов. Таким обра-Глава 11. Наследование317зом, массив типа o b j e c t в этой программе может хранить значения любого типа.
Этоговорит о том, что object-массив по сути представляет собой обобщенный список.Развивая эту идею, нетрудно создать класс стека, который бы хранил ссылки на объекты класса o b j e c t . Это позволило бы стеку сохранять данные любого типа.Несмотря на эффективность такого обобщенного типа, как класс object, в некоторых ситуациях, было бы ошибкой думать, что класс o b j e c t следует использоватькак способ обойти строгий С#-контроль соответствия типов. Другими словами, дляхранения int-значения используйте int-переменную, для хранения s t r i n g значения — string-ссылку и т.д. Оставьте обобщенную природу класса o b j e c t дляособых ситуаций.318Часть I.