Это один из мини-сериалов, который охватывает различия в перегрузках, тенях и переопределениях в VB.NET. Эта статья охватывает переопределения. Статьи, которые охватывают другие, здесь:
-> Перегрузки
-> Тени
Эти методы может быть очень запутанным; Есть много комбинаций этих ключевых слов и основных вариантов наследования. Собственная документация Microsoft не начинает раскрывать тему, и в Интернете есть много плохой или устаревшей информации. Лучший совет, чтобы быть уверенным, что ваша программа написана правильно: «Тестируйте, тестируйте и тестируйте снова». В этой серии мы рассмотрим их по одному за раз с акцентом на различия.
Переопределение
Общим для Shadows, Overloads и Overrides является то, что они повторно используют имена элементов при изменении того, что происходит. Тени и перегрузки могут работать как внутри одного класса, так и когда класс наследует другой класс. Однако переопределения можно использовать только в производном классе (иногда называемом дочерним классом), который наследуется от
базовый класс (иногда называется родительским классом). И Overrides это молоток; это позволяет полностью заменить метод (или свойство) из базового класса.В статье о классах и ключевом слове Shadows (см.: Shadows в VB.NET) была добавлена функция, показывающая, что на унаследованную процедуру можно ссылаться.
Открытый класс ProfessionalContact. '... код не отображается... Публичная функция HashTheName ( ByVal nm As String) As String. Вернуть нм. GetHashCode. Конечная функция. Конечный класс.
Код, который создает экземпляр класса, производного от этого (в этом примере CodedProfessionalContact), может вызывать этот метод, потому что он наследуется.
В примере я использовал VB.NET GetHashCode метод, чтобы сохранить код простым, и это вернуло довольно бесполезный результат, значение -520086483. Предположим, я хотел получить другой результат, но
-> Я не могу изменить базовый класс. (Может быть, все, что у меня есть, это скомпилированный код от поставщика.)
... и ...
-> Я не могу изменить код вызова (возможно, существует тысяча копий, и я не могу их обновить.)
Если я могу обновить производный класс, то я могу изменить возвращаемый результат. (Например, код может быть частью обновляемой DLL.)
Есть одна проблема. Поскольку он настолько всеобъемлющий и мощный, у вас должно быть разрешение от базового класса для использования переопределений. Но хорошо разработанные библиотеки кода обеспечивают это. (Ваш Все библиотеки кода хорошо спроектированы, верно?) Например, только что использованная нами функция Microsoft является перезаписываемой. Вот пример синтаксиса.
Открытая переопределяемая функция GetHashCode As Integer
Так что это ключевое слово должно присутствовать и в нашем базовом классе.
Открытая переопределяемая функция HashTheName ( ByVal nm As String) As String.
Переопределение метода теперь так же просто, как предоставить новый с ключевым словом Overrides. Visual Studio снова начинает работу, заполняя код автозаполнением. Когда вы входите ...
Открытая функция переопределений HashTheName (
Visual Studio автоматически добавляет остальную часть кода, как только вы вводите открывающую скобку, включая оператор return, который вызывает только исходную функцию из базового класса. (Если вы просто добавляете что-то, обычно это хорошо сделать после того, как ваш новый код все равно будет выполнен.)
Открытая функция переопределений HashTheName ( нм как строка) как строка Верните MyBase. HashTheName (нм) Конечная функция.
В этом случае, однако, я собираюсь заменить метод на что-то другое, столь же бесполезное, чтобы проиллюстрировать, как это делается: функция VB.NET, которая перевернет строку.
Открытая функция переопределений HashTheName ( нм как строка) как строка Верните Microsoft. Visual Basic. StrReverse (нм) Конечная функция.
Теперь вызывающий код получает совершенно другой результат. (Сравните с результатом в статье о тенях.)
ContactID: 246. BusinessName: Злодейские победители, GmbH. Хэш BusinessName: HbmG, sretaefeD nialliV.
Вы также можете переопределить свойства. Предположим, вы решили, что значения ContactID, превышающие 123, не будут разрешены и по умолчанию должны равняться 111. Вы можете просто переопределить свойство и изменить его при сохранении свойства:
Private _ContactID As Integer. Public Overrides Свойство ContactID как целое число. Получить. Вернуть _ContactID. Конец Get. Установить (значение ByVal как целое число) Если значение> 123, то. _ContactID = 111. Else. _ContactID = значение. Конец если. Конец указан. Конечная недвижимость.
Тогда вы получите этот результат, когда передано большее значение:
ContactID: 111. BusinessName: Damsel Rescuers, LTD.
Кстати, в примере кода пока целочисленные значения удваиваются в New подпрограмма (См. Статью о тенях), поэтому целое число 123 изменяется на 246, а затем снова изменяется на 111.
VB.NET дает вам еще больше контроля, позволяя базовому классу специально требовать или запрещать переопределение производного класса с помощью ключевых слов MustOverride и NotOverridable в базовом классе. Но оба они используются в довольно специфических случаях. Во-первых, NotOverridable.
Поскольку для общедоступного класса по умолчанию используется значение NotOverridable, зачем вам когда-либо указывать его? Если вы попробуете это в функции HashTheName в базовом классе, вы получите синтаксическую ошибку, но текст сообщения об ошибке даст вам подсказку:
NotOverridable нельзя указывать для методов, которые не переопределяют другой метод.
По умолчанию для переопределенного метода как раз наоборот: переопределяемый. Поэтому, если вы хотите, чтобы переопределение определенно остановилось на этом, вы должны указать NotOverridable для этого метода. В нашем примере кода:
Public NotOverridable Переопределение Функция HashTheName (...
Тогда, если класс CodedProfessionalContact, в свою очередь, наследуется ...
Открытый класс NotOverridableEx. Наследует CodedProfessionalContact.
... функция HashTheName не может быть переопределена в этом классе. Элемент, который нельзя переопределить, иногда называют запечатанным элементом.
Фундаментальная часть .NET Foundation это требует, чтобы цель каждого класса была явно определена, чтобы удалить все неопределенности. Проблема в предыдущих языках ООП называлась «хрупкий базовый класс». Это происходит, когда база класс добавляет новый метод с тем же именем, что и имя метода в подклассе, который наследуется от базы учебный класс. Программист, пишущий подкласс, не планировал переопределять базовый класс, но в любом случае это именно то, что происходит. Известно, что это привело к крику израненного программиста: «Я ничего не изменил, но моя программа упала в любом случае. "Если есть вероятность, что класс будет обновлен в будущем и создаст эту проблему, объявите его как NotOverridable.
MustOverride чаще всего используется в так называемом абстрактном классе. (В C # то же самое использует ключевое слово Abstract!) Это класс, который просто предоставляет шаблон, и вы должны заполнить его собственным кодом. Microsoft предоставляет этот пример одного:
Публичный MustInherit Класс Стиральная машина. Sub New () Код для создания экземпляра класса идет сюда. Конец подп. Общественный MustOverride Sub Wash. Public MustOverride Sub Rinse (loadSize as Integer) Открытая функция MustOverride Spin (скорость как целое число) как Long. Конечный класс.
Продолжая пример Microsoft, стиральные машины будут делать эти вещи (Wash, Rinse и Spin) совершенно по-другому, поэтому нет смысла определять функцию в базовом классе. Но есть преимущество в том, чтобы убедиться, что любой класс, который наследует этот делает определить их. Решение: абстрактный класс.
Если вам нужно более подробное объяснение различий между перегрузками и переопределениями, в кратком совете разработан совершенно другой пример: перегрузки и переопределения
VB.NET дает вам еще больший контроль, позволяя базовому классу специально требовать или запрещать переопределение производного класса, используя ключевые слова MustOverride и NotOverridable в базовом классе. Но оба они используются в довольно специфических случаях. Во-первых, NotOverridable.
Поскольку для общедоступного класса по умолчанию используется значение NotOverridable, зачем вам когда-либо указывать его? Если вы попробуете это в функции HashTheName в базовом классе, вы получите синтаксическую ошибку, но текст сообщения об ошибке даст вам подсказку:
NotOverridable нельзя указывать для методов, которые не переопределяют другой метод.
По умолчанию для переопределенного метода как раз наоборот: переопределяемый. Поэтому, если вы хотите, чтобы переопределение определенно остановилось на этом, вы должны указать NotOverridable для этого метода. В нашем примере кода:
Public NotOverridable Переопределение Функция HashTheName (...
Тогда, если класс CodedProfessionalContact, в свою очередь, наследуется ...
Открытый класс NotOverridableEx. Наследует CodedProfessionalContact.
... функция HashTheName не может быть переопределена в этом классе. Элемент, который нельзя переопределить, иногда называют запечатанным элементом.
Фундаментальной частью .NET Foundation является требование, чтобы цель каждого класса была явно определена, чтобы устранить все неопределенности. Проблема в предыдущих языках ООП называлась «хрупкий базовый класс». Это происходит, когда база класс добавляет новый метод с тем же именем, что и имя метода в подклассе, который наследуется от базы учебный класс. Программист, пишущий подкласс, не планировал переопределять базовый класс, но в любом случае это именно то, что происходит. Известно, что это привело к крику израненного программиста: «Я ничего не изменил, но моя программа упала в любом случае. "Если есть вероятность, что класс будет обновлен в будущем и создаст эту проблему, объявите его как NotOverridable.
MustOverride чаще всего используется в так называемом абстрактном классе. (В C # то же самое использует ключевое слово Abstract!) Это класс, который просто предоставляет шаблон, и вы должны заполнить его собственным кодом. Microsoft предоставляет этот пример одного:
Публичный MustInherit Класс Стиральная машина. Sub New () Код для создания экземпляра класса идет сюда. Конец подп. Общественный MustOverride Sub Wash. Public MustOverride Sub Rinse (loadSize as Integer) Открытая функция MustOverride Spin (скорость как целое число) как Long. Конечный класс.
Продолжая пример Microsoft, стиральные машины будут делать эти вещи (Wash, Rinse и Spin) совершенно по-другому, поэтому нет смысла определять функцию в базовом классе. Но есть преимущество в том, чтобы убедиться, что любой класс, который наследует этот делает определить их. Решение: абстрактный класс.
Если вам нужно более подробное объяснение различий между перегрузками и переопределениями, в кратком совете разработан совершенно другой пример: перегрузки и переопределения