Jaki jest odpowiednik ostatecznej wersji Java w C #?

559

Co jest równoważne Javie finalw C #?

Nosrama
źródło
131
Komentarz na szczycie klasy mówiący: „Jeśli przesłonisz tę klasę, zostaniesz zwolniony!” (oczywiście, że to żart :)
Hemant

Odpowiedzi:

860

finalKluczowe ma kilka zwyczajów w Javie. Odpowiada zarówno słowom kluczowym, jak sealedi readonlysłowom kluczowym w języku C #, w zależności od kontekstu, w którym jest używany.

Klasy

Aby zapobiec podklasom (dziedziczeniu po zdefiniowanej klasie):

Jawa

public final class MyFinalClass {...}

DO#

public sealed class MyFinalClass {...}

Metody

Zapobiegaj zastąpieniu virtualmetody.

Jawa

public class MyClass
{
    public final void myFinalMethod() {...}
}

DO#

public class MyClass : MyBaseClass
{
    public sealed override void MyFinalMethod() {...}
}

Jak zauważa Joachim Sauer, zauważalną różnicą między tymi dwoma językami jest to, że Java domyślnie oznacza wszystkie metody niestatyczne jako virtual, natomiast C # oznacza je jako sealed. Dlatego też musisz użyć sealedsłowa kluczowego w języku C #, jeśli chcesz zatrzymać dalsze zastępowanie metody, która została wyraźnie oznaczona virtualw klasie bazowej.

Zmienne

Aby umożliwić przypisanie zmiennej tylko raz:

Jawa

public final double pi = 3.14; // essentially a constant

DO#

public readonly double pi = 3.14; // essentially a constant

Na marginesie, efekt readonlysłowa kluczowego różni się od constsłowa kluczowego tym, że readonlywyrażenie jest oceniane w czasie wykonywania, a nie w czasie kompilacji , co pozwala na dowolne wyrażenia.

Noldorin
źródło
15
Dodałbym, że wszystkie metody niestatyczne w Javie są domyślnie wirtualne. Podczas gdy w C # możesz po prostu pominąć wirtualną w początkowej definicji, musisz użyć „ostatecznego”, aby uniknąć zastąpienia go przez podklasy w Javie
Joachim Sauer
166
dobra odpowiedź - jest jeszcze jedno użycie „końcowego” w Javie - na zmiennej lokalnej lub parametrze metody, aby zapobiec jej ponownemu przypisaniu. Nie ma bezpośredniego odpowiednika tego c #.
serg10
17
readonlyzmienne składowe mogą być modyfikowane w konstruktorach: pastebin.com/AzqzYGiA
rekurencyjny
8
Uwaga: jeśli zadeklarujesz zmienną składową jako ostateczną w Javie, kompilator będzie narzekał, jeśli nie każdy konstruktor przypisuje wartość w każdej ścieżce kodu, podczas gdy C # wydaje ostrzeżenie tylko w tym scenariuszu z tylko zmiennymi
składowymi
1
@NickolayKondratyev: Tak, mój przykład był domyślny, ponieważ musisz być podklasą innej klasy. Naprawdę nie potrzebujesz interfejsu; to jest zbyteczne, ale poza tym wygląda to dobrze.
Noldorin,
180

To zależy od kontekstu.

  • Dla finalklasy lub metody odpowiednikiem C # jestsealed .
  • W przypadku finalpola odpowiednikiem C # jestreadonly .
  • Dla finalzmiennej lokalnej lub parametru metody nie ma bezpośredniego odpowiednika C #.
Łukasz
źródło
1
W rzeczywistości nie ma wymogu przypisywania zmiennej końcowej podczas deklarowania. „końcowy” oznacza, że ​​zmienna musi zostać przypisana przez jakąś ścieżkę kodu przed odwołaniem się do niej i żadna ścieżka kodu nie pozwala na przypisanie zmiennej więcej niż jeden raz. Odnosi się to do zmiennych instancji, co w efekcie oznacza, że ​​konstruktorzy muszą jawnie przypisać zmienną.
Jay
31
+ za For a final local variable or method parameter, there's no direct C# equivalentogromne wyróżnienie.
Daniel B. Chapman
1
Jeśli tworzysz instancję , możesz użyć const dla zmiennej lokalnej. To nie jest równoważne, ponieważ oczywiście finał pozwala osobno zadeklarować i zainicjować (a więc mieć różne wartości), ale na wypadek, gdybyś nie wiedział ...
Griknok
3
constmożna stosować tylko w przypadku typów wartości. O ile mi wiadomo, nie ma sposobu, aby stworzyć efektywną stałą dla lokalnego typu odniesienia.
żartuje
2
@jocull Z łańcuchami stanowi jedyny wyjątek.
Raimund Krämer,
46

To, czego tu wszyscy brakuje, to gwarancja Java dla definitywnego przypisania ostatecznych zmiennych składowych.

W przypadku klasy C z końcową zmienną składową V każda możliwa ścieżka wykonania przez każdego konstruktora C musi przypisać V dokładnie jeden raz - niepowodzenie przypisania V lub przypisanie V dwa lub więcej razy spowoduje błąd.

Słowo kluczowe readonly w C # nie ma takiej gwarancji - kompilator chętnie pozostawia członków readonly nieprzypisanymi lub pozwala ci przypisywać je wielokrotnie w konstruktorze.

Zatem ostateczny i tylko do odczytu (przynajmniej w odniesieniu do zmiennych składowych) zdecydowanie nie są równoważne - końcowy jest znacznie bardziej rygorystyczny.

Jakiś facet
źródło
7

Jak wspomniano, sealedjest odpowiednikiem finalmetod i klas.

Jeśli chodzi o resztę, jest to skomplikowane.

  • W przypadku static finalpól static readonlyjest to najbliższa możliwa rzecz. Pozwala na inicjalizację pola statycznego w konstruktorze statycznym, który jest dość podobny do statycznego inicjalizatora w Javie. Dotyczy to zarówno stałych (prymitywów i obiektów niezmiennych), jak i stałych odniesień do obiektów zmiennych.

    constModyfikator jest dość podobna do stałych, ale nie można ustawić je w konstruktorze statycznym.

  • readonlyMożna użyć pola, które nie powinno zostać ponownie przypisane po opuszczeniu konstruktora . Nie jest jednak równy - finalwymaga dokładnie jednego przypisania, nawet w konstruktorze lub inicjalizatorze.
  • Nie ma odpowiednika C # dla finalzmiennej lokalnej, o której wiem. Jeśli zastanawiasz się, dlaczego ktokolwiek miałby go potrzebować: możesz zadeklarować zmienną przed if-else, skrzynką lub tym podobnym. Deklarując to jako ostateczne, egzekwujesz, że jest on przypisany maksymalnie raz.

    Zasadniczo zmienne lokalne Java muszą zostać przypisane przynajmniej raz przed ich odczytaniem. O ile gałąź nie wyskoczy przed odczytaniem wartości, zmienna końcowa jest przypisywana dokładnie raz. Wszystko to sprawdzane jest podczas kompilacji. Wymaga to dobrze zachowującego się kodu z mniejszym marginesem błędu.

Podsumowując, C # nie ma bezpośredniego odpowiednika final. Podczas gdy Java nie posiada kilku fajnych funkcji C #, dla mnie jako odświeżającego programisty Javy jest to odświeżenie, aby zobaczyć, gdzie C # nie zapewnia odpowiednika.

Vlasec
źródło
6

Ostateczne klasy Java i końcowe metody -> zapieczętowane. Ostateczna zmienna elementu Java -> tylko do odczytu dla stałej czasu wykonywania, const dla stałej czasu kompilacji.

Brak odpowiednika dla ostatecznej zmiennej lokalnej i argumentu końcowego metody

Vijayakumarpl
źródło
0

zapieczętowany

x2.
źródło
8
To tylko część odpowiedzi, ponieważ zależy od kontekstu i dodania wyjaśnień i / lub przykładów sprawi, że będzie ona bardziej strawna dla osób potrzebujących pomocy
Rune FS