Przeczytałem sobie wywiad z Andersem Hejlsbergiem nt tego czemu w C# jest w ogóle wymóg stosowania słowa virtual
jeśli chcemy mieć metodę wirtualną: http://www.artima.com/intv/nonvirtual.html
Są dwa argumenty.
Pierwszy to wydajność i jego rozumiem. .NET ma słabego JITa i nie radzi sobie z metodami wirtualnymi. JVM natomiast nie ma problemu i nawet wirtualne gettery, settery, hashcode'y, equalsy itd nie powodują spadku wydajności.
To nie tak, że .NET ma słabego JITa - po prostu ponieważ mało metod jest wirtualnych, to dewirtualizacja nie była nigdy istotnym problemem. Gdyby JVM nie miał dewirtualizacji to by strasznie ssał wydajnościowo, więc musiano to zaimplementować. A Hejlsberg w przeciwieństwie do Ciebie widział Javę w czasach, gdy brak dewirtualizacji powodował problemy wydajnościowe.
Hejlsberg popełnił też błąd przy opisywaniu Javy: We can observe that as people write code in Java, they forget to mark their methods final. Therefore, those methods are virtual.
. final
wcale nie wyklucza wirtualności metody
Nie popełnił błędu, po prostu nie znasz Javy. To się nie skompiluje:
class C extends B {
@Override
void m() {
System.out.println("C");
}
}
Final kończy możliwości nadpisywania metody: You use the final keyword in a method declaration to indicate that the method cannot be overridden by subclasses.
I o to mu chodziło, metoda jest wirtualna dopóki jej jawnie nie sfinalizujesz. A nadmiar wirtualnych metod to problem dla maszyny wirtualnej.
Drugi argument to jakieś bajeczki o wersjonowaniu i tym, że konflikty nazw w Javie powodują problemy przy aktualizacji wersji Javy. Tu się gość grubo pomylił, bo problemy z aktualizacją Javy wynikają z intensywnego użycia refleksji i wzbogacania bajtkodu. Jeżeli narzędzie analizujące bajtkod jest przystosowane do Javy X, a Java X+1 ma dodatkowe konstrukcje w bajtkodzie to to narzędzie się sypnie.
Tak, to on się pomylił, mimo że widział Javę wcześniej niż Ty, a języki programowania projektował kiedy jeszcze Ciebie na świecie nie było. :-)
Jak dla mnie to zabawa z override
, new
itd to próba ratowania syfiastego kodu (nadużywającego dziedziczenia) zamiast naprawiania go (poprzez kompozycję, czyli trzymanie się zasady SRP).
Tyle, że jak już wiemy kod nadużywający dziedziczenia łatwiej napisać w Javie, bo trzeba włożyć większy wysiłek, żeby dziedziczenia zabronić.
I w sumie po całej tej dyskusji zrozumiałem chyba narzekanie @jarekr000000 na IoC i interceptory. Faktycznie, skoro domyślnie każda metoda jest wirtualna, to nieostrożnie napisany i użyty interceptor może odstawiać w aplikacji jakąś niedebugowalną czarną magię. W C# nie ma tego problemu - od razu widać w kodzie, co potencjalnie może być wywoływane przez interceptor.
A więc według niego możliwość posiadania dwóch osobnych hierarchii metod wirtualnych (o tej samej sygnaturze) w jednej hierarchii dziedziczenia klasy to zaleta nad Javą i główny powód (bo drugi powód to kiepski JIT w .NETu) dla wprowadzenia takich kombinacji w C#. mind=blown
W ogóle nie zrozumiałeś problemu, który w ten sposób został rozwiązany:
Whenever they introduce a new method in a base class, if someone in a derived class had a method of that same name, that method is now an override—except if it has a different return type, it no longer compiles. The problem is that Java, and also C++, does not capture the intent of the programmer with respect to virtual.
W ogóle o tym rzekomym problemie z wersjonowaniem w Javie pierwszy raz przeczytałem właśnie w wywiadzie z Hejlsbergiem. Wygląda więc na to, że Hejlsberg "naprawił" problem który nie istnieje.
Tak właśnie było, sam widziałem! :-)
C# z powodu swojej alergii na metody wirtualne wybrał statyczne metody rozszerzające by dodać funkcjonalności do istniejących klas w bibliotece standardowej. Ma to tę wadę, iż konkretne klasy nie są w stanie bezpośrednio nadpisać nowej metody implementując funkcjonalność w bardziej efektywny sposób, tzn przy użyciu referencji o typie interfejsu zawsze zostanie użyta domyślna metoda statyczna (rozszerzająca).
To nie jest alergia na metody wirtualne - to pragmatyzm, w programowaniu występujący pod nazwą YAGNI, na który rzekomo też się powołujesz.
Podobnie jak pragmatyzmem jest czynienie rzeczy bezstanowych statycznymi.
Nie jestem spięty. Po prostu nie lubię jak ktoś mi wciska kit :]
No tak, o swój monopol trzeba dbać. ;)