Това е една от мини-сериите, която покрива разликите в Overloads, Shadows и Overrides във VB.NET. Тази статия обхваща отмените. Статиите, които обхващат останалите, са тук:
-> Претоварвания
-> Сенки
Тези техники може да бъде много объркващо; има много комбинации от тези ключови думи и основните опции за наследяване. Собствената документация на Microsoft не започва да върши темата справедливо и в интернет има много лоша или остаряла информация. Най-добрият съвет, за да сте сигурни, че програмата ви е кодирана правилно, е „Тествайте, тествайте и тествайте отново“. В тази серия ще ги разгледаме един по един с акцент върху разликите.
Замени на
Нещото, което Shadows, Overloads и Overrides имат общо, е, че използват повторно името на елементите, докато променят случващото се. Сенките и претоварванията могат да работят както в един клас, така и когато клас наследява друг клас. Отмяна, обаче, може да се използва само в производен клас (понякога наричан детски клас), който наследява от a базов клас (понякога се нарича родителски клас). И Overrides е чукът; тя ви позволява изцяло да замените метод (или свойство) от базов клас.
В статията за класовете и ключовата дума Shadows (Вижте: Shadows във VB.NET) беше добавена функция, която показва, че наследствена процедура може да се направи препратка.
Public Class ProfessionalContact. '... кодът не е показан... Публична функция HashTheName ( ByVal nm As String) Като струнен. Връщане nm. GetHashCode. Крайна функция Краен клас
Кодът, който създава клас, получен от този (CodedProfessionalContact в примера), може да извика този метод, защото е наследен.
В примера използвах VB.NET GetHashCode метод за запазване на кода прост и това върна доста безполезен резултат, стойността -520086483. Да предположим, че вместо това исках да се върне различен резултат,
-> Не мога да променя базовия клас. (Може би всичко, което имам, е съставен код от доставчик.)
... и ...
-> Не мога да променя кода за повикване (Може би има хиляди копия и не мога да ги актуализирам.)
Ако мога да актуализирам получения клас, тогава мога да променя резултата, върнат. (Например, кодът може да бъде част от актуализируем DLL.)
Има един проблем. Тъй като е толкова всеобхватен и мощен, трябва да имате разрешение от базовия клас, за да използвате Overrides. Но добре проектираните кодови библиотеки го предоставят. (Вашият всички библиотеки с код са добре проектирани, нали?) Например, предоставената от Microsoft функция, която току-що използвахме, е заменяема. Ето пример за синтаксиса.
Публична функция за презаписване GetHashCode като цяло число
Така че тази ключова дума трябва да присъства и в нашия примерен базов клас.
Публична функция за заменяне HashTheName ( ByVal nm As String) Като струнен.
Отмяна на метода сега е толкова просто, колкото предоставянето на нов с ключовата дума Overrides. Visual Studio отново ви дава начален старт, като попълвате кода за вас с AutoComplete. Когато въведете ...
Публично отменя функция HashTheName (
Visual Studio автоматично добавя останалата част от кода веднага щом въведете отварящите скоби, включително оператора за връщане, който извиква само оригиналната функция от базовия клас. (Ако просто добавяте нещо, обикновено това е добре да направите, след като вашият нов код все пак се изпълни.)
Публично отменя функция HashTheName ( nm като струнен) като струнен. Върнете MyBase. HashTheName (nm) Крайна функция
В този случай обаче ще заменя метода с нещо друго също толкова безполезно, само за да илюстрирам как се прави: Функцията VB.NET, която ще обърне низ.
Публично отменя функция HashTheName ( nm като струнен) като струнен. Върнете Microsoft. VisualBasic. StrReverse (nm) Крайна функция
Сега обаждащият се код получава съвсем различен резултат. (Сравнете с резултата в статията за сенките.)
ContactID: 246. BusinessName: Villain Defeaters, GmbH. Hash на BusinessName: HbmG, sretaefeD nialliV.
Можете също да отмените свойствата. Да предположим, че сте решили, че стойностите на ContactID по-големи от 123 няма да бъдат разрешени и трябва да бъдат по подразбиране на 111. Можете просто да отмените свойството и да го промените, когато собствеността е запазена:
Частен _ContactID като цяло число. Публично отменя собствеността ContactID като цяло число. Вземете. Връщане _ContactID. Край Вземете. Задаване (ByVal стойност като цяло число) Ако стойност> 123 Тогава. _ContactID = 111. Else. _ContactID = стойност. Край Ако. Краен комплект. Крайна собственост.
След това получавате този резултат, когато се предава по-голяма стойност:
ContactID: 111. BusinessName: Спасители на Дамсел, ООД
Между другото, в примерния код досега целите стойности се удвояват в Новото подпрограма (Вижте статията за Shadows), така че цяло число от 123 се променя на 246 и след това отново се променя на 111.
VB.NET ви дава още повече контрол, като позволява на базовия клас специално да изисква или отказва производен клас да презамени с помощта на ключовите думи MustOverride и NotOverridable в базовия клас. Но и двете се използват в доста конкретни случаи. Първо, NotOverridable.
Тъй като по подразбиране за публичен клас е NotOverridable, защо изобщо трябва да го определяте? Ако го опитате на функцията HashTheName в базовия клас, получавате синтактична грешка, но текстът на съобщението за грешка ви дава представа:
„NotOverridable“ не може да бъде посочен за методи, които не отменят друг метод.
По подразбиране за отменен метод е точно обратното: Overrideable. Така че, ако искате да отмените определено да спрете, трябва да посочите NotOverridable на този метод. В нашия примерен код:
Обществено NotOverridable Замени на Функция HashTheName (...
Тогава ако класът CodedProfessionalContact от своя страна е наследен ...
Публичен клас NotOverridableEx. Наследяния CodedProfessionalContact.
... функцията HashTheName не може да бъде отменена в този клас. Елемент, който не може да бъде отменен, понякога се нарича запечатан елемент.
Основна част от на.Фондация NET е да изисква целта на всеки клас да е изрично дефинирана, за да се премахне цялата несигурност. Проблем в предишните езици на OOP се нарича „крехката базова класа“. Това се случва, когато база клас добавя нов метод със същото име като име на метод в подклас, който наследява от база клас. Програмистът, който пише подклас, не планира да замени базовия клас, но точно така се случва. Известно е, че това води до вика на ранения програмист: „Не промених нищо, но програмата ми се срине така или иначе. "Ако има възможност класът да бъде актуализиран в бъдеще и да създаде този проблем, декларирайте го като NotOverridable.
MustOverride най-често се използва в това, което се нарича абстрактна класа. (В C #, същото нещо използва ключовата дума Абстракт!) Това е клас, който просто предоставя шаблон и се очаква да го попълните със собствен код. Microsoft предоставя този пример за едно:
Обществена машина за пране на клас MustInherit. Sub New () „Кодът за инстанциране на класа идва тук. Край подс. Обществено MustOverride Sub Wash. Обществено MustOverride Sub Rinse (loadSize as Integer) Публична функция MustOverride Spin (скорост като цяло число) като дълга. Краен клас
За да продължат примера на Microsoft, пералните машини ще правят тези неща (измиване, изплакване и завъртане) по съвсем различен начин, така че няма предимство да дефинирате функцията в базовия клас. Но има предимство в това да се уверите, че всеки клас, който наследява този прави дефинирайте ги. Решението: абстрактен клас.
Ако имате нужда от още обяснение за разликите между Overloads и Overrides, в един бърз съвет е разработен съвсем различен пример: Overloads Versus Overrides
VB.NET ви осигурява още по-голям контрол, като позволява на базовия клас да изиска или откаже производен клас да отмени, използвайки ключовите думи MustOverride и NotOverridable в базовия клас. Но и двете се използват в доста конкретни случаи. Първо, NotOverridable.
Тъй като по подразбиране за публичен клас е NotOverridable, защо изобщо трябва да го определяте? Ако го опитате на функцията HashTheName в базовия клас, получавате синтактична грешка, но текстът на съобщението за грешка ви дава представа:
„NotOverridable“ не може да бъде посочен за методи, които не отменят друг метод.
По подразбиране за отменен метод е точно обратното: Overrideable. Така че, ако искате да отмените определено да спрете, трябва да посочите NotOverridable на този метод. В нашия примерен код:
Обществено NotOverridable Замени на Функция HashTheName (...
Тогава ако класът CodedProfessionalContact от своя страна е наследен ...
Публичен клас NotOverridableEx. Наследяния CodedProfessionalContact.
... функцията HashTheName не може да бъде отменена в този клас. Елемент, който не може да бъде отменен, понякога се нарича запечатан елемент.
Основна част от .NET Foundation е да изисква целта на всеки клас да бъде изрично дефинирана, за да се премахне цялата несигурност. Проблем в предишните езици на OOP се нарича „крехката базова класа“. Това се случва, когато база клас добавя нов метод със същото име като име на метод в подклас, който наследява от база клас. Програмистът, който пише подклас, не планира да замени базовия клас, но точно така се случва. Известно е, че това води до вика на ранения програмист: „Не промених нищо, но програмата ми се срине така или иначе. "Ако има възможност класът да бъде актуализиран в бъдеще и да създаде този проблем, декларирайте го като NotOverridable.
MustOverride най-често се използва в това, което се нарича абстрактна класа. (В C #, същото нещо използва ключовата дума Абстракт!) Това е клас, който просто предоставя шаблон и се очаква да го попълните със собствен код. Microsoft предоставя този пример за едно:
Обществена машина за пране на клас MustInherit. Sub New () „Кодът за инстанциране на класа идва тук. Край подс. Обществено MustOverride Sub Wash. Обществено MustOverride Sub Rinse (loadSize as Integer) Публична функция MustOverride Spin (скорост като цяло число) като дълга. Краен клас
За да продължат примера на Microsoft, пералните машини ще правят тези неща (измиване, изплакване и завъртане) по съвсем различен начин, така че няма предимство да дефинирате функцията в базовия клас. Но има предимство в това да се уверите, че всеки клас, който наследява този прави дефинирайте ги. Решението: абстрактен клас.
Ако имате нужда от още обяснение за разликите между Overloads и Overrides, в един бърз съвет е разработен съвсем различен пример: Overloads Versus Overrides