Przesłania w VB.NET

Jest to jedna z mini-serii, która obejmuje różnice w przeciążeniach, cieniach i przesłonięciach VB.NET. W tym artykule omówiono Zastąpienia. Artykuły dotyczące innych znajdują się tutaj:

-> Przeciążenia
-> Cienie

Te techniki może być bardzo mylące; istnieje wiele kombinacji tych słów kluczowych i podstawowych opcji dziedziczenia. Własna dokumentacja Microsoftu nie zaczyna oddawać tematu, a w sieci jest wiele złych lub nieaktualnych informacji. Najlepszą radą, aby upewnić się, że program jest poprawnie zakodowany, jest: „Testuj, testuj i testuj ponownie”. W tej serii przyjrzymy się im pojedynczo, z naciskiem na różnice.

Zastępuje

Cienie, przeciążenia i przesłonięcia mają wspólną cechę polegającą na tym, że używają nazwy elementów, zmieniając to, co się dzieje. Cienie i Przeciążenia mogą działać zarówno w obrębie tej samej klasy, jak i gdy dziedziczy klasy inna klasa. Zastąpienia można jednak użyć tylko w klasie pochodnej (czasami nazywanej klasą potomną), która dziedziczy po klasa podstawowa (czasami nazywany klasą nadrzędną). I Zastępuje młot; pozwala całkowicie zastąpić metodę (lub właściwość) z klasy podstawowej.

instagram viewer

W artykule na temat klas i słowa kluczowego Shadows (patrz: Cienie w VB.NET) dodano funkcję pokazującą, że można odwoływać się do odziedziczonej procedury.

Public Class ProfessionalContact. '... kod nie pokazano... Funkcja publiczna HashTheName ( ByVal nm As String) As String. Zwróć nm. GetHashCode. Funkcja zakończenia. Klasa końcowa.

Kod, który tworzy instancję klasy pochodnej od tej (CodedProfessionalContact w przykładzie) może wywołać tę metodę, ponieważ jest dziedziczona.

W przykładzie użyłem VB.NET GetHashCode metoda uproszczenia kodu, co zwróciło dość bezużyteczny wynik, wartość -520086483. Załóżmy, że chciałbym zamiast tego zwrócić inny wynik, ale,

-> Nie mogę zmienić klasy podstawowej. (Może wszystko, co mam, to skompilowany kod od dostawcy).

... i ...

-> Nie mogę zmienić kodu dzwoniącego (być może jest ich tysiące i nie mogę ich zaktualizować).

Jeśli mogę zaktualizować klasę pochodną, ​​mogę zmienić zwrócony wynik. (Na przykład kod może być częścią biblioteki DLL, którą można aktualizować).

Jest jeden problem. Ponieważ jest tak wszechstronny i potężny, musisz mieć pozwolenie od klasy podstawowej, aby używać Zastąpień. Ale zapewniają to dobrze zaprojektowane biblioteki kodów. (Twój biblioteki kodów są dobrze zaprojektowane, prawda?) Na przykład funkcja Microsoft, której właśnie użyliśmy, jest nadpisywalna. Oto przykład składni.

Public Overridable Function GetHashCode As Integer

Dlatego to słowo kluczowe musi być obecne również w naszej przykładowej klasie bazowej.

Public Overridable Function HashTheName ( ByVal nm As String) As String.

Przesłanianie metody jest teraz tak proste, jak udostępnienie nowego ze słowem kluczowym Zastępuje. Program Visual Studio ponownie umożliwia rozpoczęcie pracy, wypełniając kod za pomocą funkcji Autouzupełniania. Po wejściu ...


Funkcja publiczna zastępuje funkcję HashTheName (

Visual Studio dodaje resztę kodu automatycznie, gdy tylko wpiszesz nawias otwierający, w tym instrukcję return, która wywołuje tylko oryginalną funkcję z klasy podstawowej. (Jeśli tylko dodajesz coś, zwykle jest to dobra rzecz po tym, jak Twój nowy kod zostanie wykonany).

Funkcja publiczna zastępuje funkcję HashTheName ( nm As String) As String. Zwróć MyBase. HashTheName (nm) Funkcja zakończenia.

W tym przypadku zamierzam jednak zastąpić metodę czymś równie bezużytecznym, aby zilustrować, jak to się robi: funkcja VB.NET, która odwróci ciąg.

Funkcja publiczna zastępuje funkcję HashTheName ( nm As String) As String. Zwróć Microsoft. Visual Basic. StrReverse (nm) Funkcja zakończenia.

Teraz kod wywołujący otrzymuje zupełnie inny wynik. (Porównaj z wynikiem w artykule o Shadows.)


ContactID: 246. BusinessName: Villain Defeaters, GmbH. Hash of the BusinessName: HbmG, sretaefeD nialliV. 

Możesz również zastąpić właściwości. Załóżmy, że zdecydowałeś, że wartości ContactID większe niż 123 nie będą dozwolone i że powinny mieć domyślnie 111. Możesz po prostu zastąpić właściwość i zmienić ją, gdy właściwość zostanie zapisana:

Prywatny _ContactID As Integer. Public Zastępuje właściwość ContactID As Integer. Otrzymać. Zwróć _ContactID. End Get. Set (wartość ByVal jako liczba całkowita) Jeśli wartość> 123, to. _ContactID = 111. Jeszcze. _ContactID = wartość. End If. Zestaw końcowy. Zakończ właściwość.

Następnie otrzymujesz ten wynik, gdy zostanie przekazana większa wartość:


ContactID: 111. BusinessName: Damsel Rescuers, LTD. 

Nawiasem mówiąc, w dotychczasowym kodzie przykładowym wartości całkowite są podwojone w Nowym podprogram (Zobacz artykuł o Shadows), więc liczba całkowita 123 jest zmieniana na 246, a następnie ponownie na 111.

VB.NET daje ci jeszcze więcej kontroli, pozwalając klasie bazowej na szczególne wymaganie lub odmowę klasy pochodnej do przesłonięcia przy użyciu słów kluczowych MustOverride i NotOverridable w klasie podstawowej. Oba są jednak stosowane w dość szczególnych przypadkach. Po pierwsze, NotOverridable.

Ponieważ domyślną klasą publiczną jest NotOverridable, dlaczego miałbyś kiedykolwiek ją określać? Jeśli wypróbujesz to w funkcji HashTheName w klasie podstawowej, pojawi się błąd składniowy, ale tekst komunikatu o błędzie daje wskazówkę:

Nie można określić „NotOverridable” dla metod, które nie zastępują innej metody.

Domyślna metoda przesłonięcia jest wręcz przeciwna: Przesłonięcie. Więc jeśli chcesz zastąpić, aby na pewno się tam zatrzymać, musisz określić NotOverridable dla tej metody. W naszym przykładowym kodzie:


Public NotOverridable Zastępuje Funkcja HashTheName (... 

Jeśli klasa CodedProfessionalContact jest z kolei dziedziczona ...


Klasa publiczna NotOverridableEx. Dziedziczy CodedProfessionalContact. 

... funkcji HashTheName nie można przesłonić w tej klasie. Element, którego nie można zastąpić, jest czasami nazywany elementem zapieczętowanym.

Zasadnicza część .Fundacja NET wymaga, aby cel każdej klasy był wyraźnie zdefiniowany w celu usunięcia wszelkiej niepewności. Problem w poprzednich językach OOP nazywano „delikatną klasą bazową”. Dzieje się tak, gdy baza klasa dodaje nową metodę o tej samej nazwie co nazwa metody w podklasie, która dziedziczy z podstawy klasa. Programista piszący podklasę nie planował przesłonić klasy bazowej, ale tak właśnie się dzieje. Wiadomo, że spowodowało to okrzyk zranionego programisty: „Nic nie zmieniłem, ale mój program się zawiesił mimo to. ”Jeśli istnieje możliwość, że klasa zostanie zaktualizowana w przyszłości i spowoduje powstanie tego problemu, zadeklaruj ją jako NotOverridable.

MustOverride jest najczęściej używany w tak zwanej klasie abstrakcyjnej. (W języku C # to samo używa słowa kluczowego Streszczenie!) Jest to klasa, która po prostu udostępnia szablon i oczekuje się, że wypełnisz go własnym kodem. Microsoft podaje ten przykład jednego z nich:

Public MustInherit Class WashingMachine. Sub New () „Kod instancji klasy znajduje się tutaj. Napis końcowy. Public MustOverride Sub Wash. Public MustOverride Sub Rinse (loadSize as Integer) Publiczny obrót funkcji MustOverride (prędkość jako liczba całkowita) jako długi. Klasa końcowa.

Kontynuując przykład Microsoftu, pralki robią te rzeczy (pranie, płukanie i wirowanie) zupełnie inaczej, więc nie ma żadnej korzyści z definiowania funkcji w klasie podstawowej. Ale zaletą jest upewnienie się, że każda klasa, która dziedziczy tę klasę robi zdefiniuj je. Rozwiązanie: klasa abstrakcyjna.

Jeśli potrzebujesz jeszcze więcej wyjaśnień na temat różnic między przeciążeniami i przesłonięciami, w szybkiej poradzie opracowano zupełnie inny przykład: przeciążenia kontra przesłonięcia

VB.NET daje jeszcze większą kontrolę, pozwalając klasie bazowej na szczególne wymaganie lub odmowę klasy pochodnej do przesłonięcia przy użyciu słów kluczowych MustOverride i NotOverridable w klasie podstawowej. Oba są jednak stosowane w dość szczególnych przypadkach. Po pierwsze, NotOverridable.

Ponieważ domyślną klasą publiczną jest NotOverridable, dlaczego miałbyś kiedykolwiek ją określać? Jeśli wypróbujesz to w funkcji HashTheName w klasie podstawowej, pojawi się błąd składniowy, ale tekst komunikatu o błędzie daje wskazówkę:

Nie można określić „NotOverridable” dla metod, które nie zastępują innej metody.

Domyślna metoda przesłonięcia jest wręcz przeciwna: Przesłonięcie. Więc jeśli chcesz zastąpić, aby na pewno się tam zatrzymać, musisz określić NotOverridable dla tej metody. W naszym przykładowym kodzie:


Public NotOverridable Zastępuje Funkcja HashTheName (... 

Jeśli klasa CodedProfessionalContact jest z kolei dziedziczona ...


Klasa publiczna NotOverridableEx. Dziedziczy CodedProfessionalContact. 

... funkcji HashTheName nie można przesłonić w tej klasie. Element, którego nie można zastąpić, jest czasami nazywany elementem zapieczętowanym.

Zasadniczą częścią .NET Foundation jest wymaganie, aby cel każdej klasy był wyraźnie zdefiniowany w celu usunięcia wszelkiej niepewności. Problem w poprzednich językach OOP nazywano „delikatną klasą bazową”. Dzieje się tak, gdy baza klasa dodaje nową metodę o tej samej nazwie co nazwa metody w podklasie, która dziedziczy z podstawy klasa. Programista piszący podklasę nie planował przesłonić klasy bazowej, ale tak właśnie się dzieje. Wiadomo, że spowodowało to okrzyk zranionego programisty: „Nic nie zmieniłem, ale mój program się zawiesił mimo to. ”Jeśli istnieje możliwość, że klasa zostanie zaktualizowana w przyszłości i spowoduje powstanie tego problemu, zadeklaruj ją jako NotOverridable.

MustOverride jest najczęściej używany w tak zwanej klasie abstrakcyjnej. (W języku C # to samo używa słowa kluczowego Streszczenie!) Jest to klasa, która po prostu udostępnia szablon i oczekuje się, że wypełnisz go własnym kodem. Microsoft podaje ten przykład jednego z nich:

Public MustInherit Class WashingMachine. Sub New () „Kod instancji klasy znajduje się tutaj. Napis końcowy. Public MustOverride Sub Wash. Public MustOverride Sub Rinse (loadSize as Integer) Publiczny obrót funkcji MustOverride (prędkość jako liczba całkowita) jako długi. Klasa końcowa.

Kontynuując przykład Microsoftu, pralki robią te rzeczy (pranie, płukanie i wirowanie) zupełnie inaczej, więc nie ma żadnej korzyści z definiowania funkcji w klasie podstawowej. Ale zaletą jest upewnienie się, że każda klasa, która dziedziczy tę klasę robi zdefiniuj je. Rozwiązanie: klasa abstrakcyjna.

Jeśli potrzebujesz jeszcze więcej wyjaśnień na temat różnic między przeciążeniami i przesłonięciami, w szybkiej poradzie opracowano zupełnie inny przykład: przeciążenia kontra przesłonięcia