Wraz z Javą 8, oprócz lambd (domknięć itp jak zwał tak zwał), mają nadejść metody rozszerzające, tzw "defender methods": http://openjdk.java.net/projects/lambda/ (podpunkt o tej samej nazwie).
Naszło mnie na zrobienie pewnego rodzaju porównania pomiędzy wspomnianymi w tytule językami jeśli chodzi o lokalne rozszerzanie funkcjonalności klas albo też wielodziedziczenie.
Defender methods to coś jak delegaty do statycznych metod rozszerzających (takich jak z C#). Różnica pomiędzy podejściem Javy i C# jest taka, że w Javie defender methods mają być wirtualne i dodaje się je do interfejsu. Jako, że w Javie można dziedziczyć po wielu interfejsach naraz to owe defender methods dadzą namiastkę mixinów ze Scali (chociaż dość kiepską namiastkę). Ponadto w dokumencie jest dość mocna sugestia, że defender methods będą zaimplementowane za pomocą invokedynamic. Jak dla mnie to dość odbieganie od pewnych założeń Javy, tzn statyczności konstrukcji językowych. Mimo wszystko defender methods są zaprojektowane tak, aby były maksymalnie kompatybilne z obecnym stylem pisania kodu Javowego.
Rozszerzanie ze Scali za pomocą konwersji implicit czy też kompozycja traitów jest wg mnie chyba najlepszym rozwiązaniem. Jest chyba najbardziej skalowalne, elastyczne i spójne, ale dalej jest całkowicie statyczną konstrukcją.
Z tego co do tej pory wydumałem (a że jest dość późno to możliwe że doszedłem do złych wniosków) wynika, że zarówno podejścia z C# jak i Javy 8 mają wady w stosunku do podejścia ze Scali. Konwersja implicit w Scali powoduje, że jedną linijką można dodać do jakiegoś typu wszystkie metody z innego typu. W Javie 8 czy C# trzeba zaklepać cały interfejs delegatów (extension methods). Podejście z C# jest całkowicie statyczne, w przeciwieństwie do podejścia z Javy 8, a więc jest zdecydowanie najgorsze pod względem skalowalności. Nie widzę jednak jak za pomocą defender methods rozszerzyć np Integera lokalnie o metody np operujące na liczbach urojonych. Z tego co wyczytałem więc extension methods z C# są właśnie po to, aby sobie lokalnie rozszerzyć dany typ o nowe metody, a defender methods z Javy 8 są po to, aby móc rozszerzać interfejsy bez potrzeby zmian w implementacjach. Konwersje implicit i wielodziedziczenie po traitach w Scali rozwiązują oba problemy.
Podsumowując: moim zdaniem podejście z C# (extension methods) to taka uboga wersja konwersji implicit ze Scali natomiast podejście z Javy 8 to dodanie namiastki mixinów ze Scali z zachowaniem kompatybilności wstecznej.
Co sądzicie o podejściach w tych językach, względnie w innych językach statycznie typowanych? MSZ extension methods z C# to co najwyżej oszczędzają kilka znaków przy wywołaniu metod, jako że zamiast ob.extensionMethod() można zrobić ext.extensionMetdhod(ob), gdzie ext to obiekt dostarczający dodatkowych metod. Defender methods z Javy natomiast dają możliwość bardzo ograniczonego wielodziedziczenia, co może znacząco zmniejszyć ilość metod do zaimplemetowania czy wydelegowania.
Nie wiem jaka jest polityka dotycząca .NETa, ale w Javie autorzy skupiają się na kompatybilności wstecznej. Defender methods są dlatego, że chcą do kolekcji dodać takie funkcje jak map(), forAll(), filter() etc nie powodując błędów kompliacji już istniejących wyspecjalizowanych, zewnętrznych implementacji kolekcji. W .NETu być może jest tak, że pod każdy numerek trzeba pisać inną wersję bibliotek/ aplikacji - nie wiem.
Kozioł i Królik lubią zabawy z zaawansowanymi funkcjonalnościami języków, więc ich zdanie by mnie ciekawiło. Deus pewnie pokazał by, że w Haskellu można to wszystko zaimplementować 30 x szybciej, ale niestety się już nie pojawia.