Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Интерфейсы. Запечатанные классы и методы

Запечатанные классы и методы

Абстрактные классы и функции

Вызов базовых версий функций

В С# предусмотрен специальный синтаксис вызова базовых версий метода из производного класса: base. <ИмяМетода> (). Например, если необходимо, чтобы метод производного класса возвращал 90% значения, возвращенного методом базового класса, можете воспользоваться следующим синтаксисом:

class CustomerAccount { public virtual decimal CalculatePrice () { // реализация return 30.0M; } }class GoldAccount: CustomerAccount { public override decimal CalculatePrice () { return base.CalculatePrice () * 0.9M; } } class Program { static void Main(string[] args) { GoldAccount x = new GoldAccount(); Console.WriteLine(x.CalculatePrice()); Console.ReadLine(); } }

Отметим, что синтаксис base.<ИмяМетода>() можно использовать для вызова любого метода базового класса — вы не обязаны вызывать его только из переопределенной версии того же метода.

Язык С# позволяет объявлять абстрактными и классы, и функции. Создавать экземпляры абстрактных классов нельзя, поскольку абстрактные функции не имеют реализации и должны быть переопределены в любом неабстрактном классе-наследнике. Очевидно, что абстрактные функции автоматически являются виртуальными (хотя вы не должны применять ключевое слово virtual, так как это приведет к синтаксической ошибке). Если любой класс содержит любую абстрактную функцию, этот класс сам является абстрактным и должен быть объявлен таковым:

abstract class Building { public abstract decimal CalculateHeatingCost (); // абстрактный метод }class MyBuilding: Building { public override decimal CalculateHeatingCost() { return 35.2M; } } class Program { static void Main(string[] args) { MyBuilding x = new MyBuilding(); Console.WriteLine(x.CalculateHeatingCost()); Console.ReadLine(); } }

Разработчики на C++ отметят также отличие в терминологии: в C++ абстрактные функции часто описываются как чистые виртуальные; в мире же С# единственный корректный термин для них — абстрактные.

С# позволяет объявлять классы и методы как sealed (запечатанные). В случае класса это значит, что наследовать от него нельзя. В случае метода это означает невозможность его переопределения.

sealed class FinalClass { // и т.д. }class DerivedClass: FinalClass // Неверно. Ошибка компиляции. { // и т.д. }

Наиболее вероятная ситуация, когда может понадобиться пометить класс или метод как sealed — это когда класс или метод обеспечивает внутренние действия библиотеки, класса или других разрабатываемых классов, поэтому вы уверены, что любая попытка переопределить некоторую его функциональность приведет к нестабильности кода. Также можно помечать класс или метод как sealed из коммерческих соображений, чтобы предотвратить использование классов способом, противоречащим лицензионным соглашениям. Вообще говоря, нужно быть осторожным с объявлением классов как sealed, потому что, поступая так, вы в некоторой степени ограничиваете возможности их использования. Даже если вы не думаете, что понадобится наследовать от класса или переопределять его члены, все же существует вероятность, что в какой-то момент в будущем кто-то столкнется с ситуацией, которую вы не смогли предвидеть. В библиотеке базовых классов.NET часто встречаются запечатанные классы. Это защищает их от независимых разработчиков, которые могут пожелать унаследовать от них собственные классы. Так, например, string — запечатанный класс. Объявление метода sealed служит той же цели, что и для класса:

class MyClass: MyClassBase { public sealed override void FinalMethod() { // и т.д. } }class DerivedClass: MyClass { public override void FinalMethod () // Неверно. Ошибка компиляции. { } }

Для того чтобы можно было применить ключевое слово sealed к методу или свойству, они должны быть сначала переопределены по отношению к базовому классу. Если вы не хотите, чтобы метод или свойство базового класса переопределялось, то просто не помечайте их как virtual.

Как упоминалось ранее, наследуя интерфейс, класс тем самым декларирует, что он реализует определенные функции. Поскольку не все объектно-ориентированные языки поддерживают интерфейсы, в этом разделе подробно описана реализация интерфейсов С#. В этом разделе интерфейсы рассматриваются путем представления полного определения одного из интерфейсов от Microsoft — System. IDisposable. Интерфейс IDisposable содержит один метод Dispose (), предназначенный для реализации классами, которые осуществляют очистку кода:

public interface IDisposable{ void Dispose();}

Этот фрагмент показывает, что объявление интерфейса синтаксически очень похоже на объявление абстрактного класса. Однако вы должны знать, что ни для одного из членов интерфейса не допускается какой-либо реализации. В общем случае, интерфейс может содержать только объявления методов, свойств, индексов и событий. Создавать экземпляр интерфейса нельзя — он содержит только сигнатуры своих членов. Интерфейс не имеет конструкторов (как можно сконструировать нечто, экземпляр чего не создается?), равно как и полей (поскольку это подразумевает некоторую внутреннюю реализацию). Определению интерфейса также не разрешено содержать перегрузки операций, причем не потому, что с этим связаны какие-то принципиальные проблемы. Причина в том, что назначение интерфейсов состоит в том, чтобы служить общедоступными контрактами, для которых перегрузка операций вызывала бы определенные

проблемы совместимости с другими языками.NET, такими как Visual Basic и.NET, которые не поддерживают перегрузку операций.

Также при определении членов интерфейса не разрешены модификаторы. Члены интерфейса всегда неявно являются public и не могут быть virtual или static. Это оставлено на усмотрение реализаций классов. Таким образом, вполне нормально указывать модификаторы доступа к членам интерфейса в реализующих их классах, что и делается в примерах настоящего раздела.

Рассмотрим, например, интерфейс IDisposable. Если класс пожелает объявить, что он реализует метод Dispose (), то он должен будет реализовать интерфейс IDisposable, что в терминах С# означает, что он наследуется от IDisposable.

class SomeClass: IDisposable { // Этот класс ДОЛЖЕН содержать реализацию // метода IDisposable.Dispose (), иначе // возникнет ошибка компиляции. public void Dispose () { // реализация метода Dispose () } // остальная часть класса }

В этом примере, если SomeClass будет наследовать IDisposable, но не будет содержать реализации Dispose (), в точности совпадающей с сигнатурой, определенной в IDisposable, будет выдана ошибка компиляции, поскольку в этом случае класс нарушит контракт реализации интерфейса IDisposable. Разумеется, для компилятора не будет никакой проблемы, если встретится класс, включающий метод Dispose (), но не унаследованный от IDisposable. Проблема будет в том, что другой код не будет иметь возможности распознать, что SomeClass согласен поддерживать средства IDisposable. IDisposable — сравнительно простой интерфейс, потому что в нем определен только один метод. Большинство интерфейсов содержат гораздо большее количество методов.

<== предыдущая лекция | следующая лекция ==>
Виртуальные методы | 
Поделиться с друзьями:


Дата добавления: 2013-12-12; Просмотров: 388; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.012 сек.