Odpowiedź:
Wikipedia ma świetny artykuł na temat programowania funkcjonalnego z niektórymi przykładami, o które prosisz. @Konrad Rudolph podał już link do artykułu OOP .
Nie sądzę, że jeden paradygmat jest super-zestawem drugiego. Są to różne perspektywy programowania i niektóre problemy można lepiej rozwiązać z jednej perspektywy, a niektóre z drugiej.
Twoje pytanie jest jeszcze bardziej skomplikowane przez wszystkie implementacje FP i OOP. Każdy język ma swoje dziwactwa, które są istotne dla każdej dobrej odpowiedzi na twoje pytanie.
Coraz bardziej styczne wędrowanie:
Podoba mi się pomysł, że język taki jak Scala stara się dać ci to, co najlepsze z obu światów. Martwię się, że daje to również komplikacje obu światów.
Java jest językiem OO, ale w wersji 7 dodano funkcję „spróbuj z zasobami”, której można użyć do naśladowania pewnego rodzaju zamknięcia. Tutaj imituje aktualizację lokalnej zmiennej „a” w środku innej funkcji, nie czyniąc jej widoczną dla tej funkcji. W tym przypadku pierwsza połowa drugiej funkcji to konstruktor ClosureTry (), a druga połowa to metoda close ().
public class ClosureTry implements AutoCloseable {
public static void main(String[] args) {
int a = 1;
try(ClosureTry ct = new ClosureTry()) {
System.out.println("Middle Stuff...");
a = 2;
}
System.out.println("a: " + a);
}
public ClosureTry() {
System.out.println("Start Stuff Goes Here...");
}
/** Interface throws exception, but we don't have to. */
public void close() {
System.out.println("End Stuff Goes Here...");
}
}
Wydajność:
Start Stuff Goes Here...
Middle Stuff...
End Stuff Goes Here...
a: 2
Może to być przydatne do zamierzonego celu, jakim jest otwarcie strumienia, zapisanie do strumienia i niezawodne zamknięcie go, lub po prostu sparowanie dwóch funkcji w taki sposób, aby nie zapomnieć o wywołaniu drugiej po wykonaniu jakiejś pracy między nimi . Oczywiście jest to tak nowe i niezwykłe, że inny programista może usunąć blok try, nie zdając sobie sprawy, że coś psuje, więc jest to obecnie rodzaj anty-wzorca, ale interesujące, że można to zrobić.
Możesz wyrazić dowolną pętlę w większości imperatywnych języków jako rekurencję. Obiekty i zmienne można uczynić niezmiennymi. Procedury mogą być napisane w celu zminimalizowania skutków ubocznych (chociaż twierdzę, że prawdziwa funkcja nie jest możliwa na komputerze - czas potrzebny do wykonania i zużycie procesora / dysku / systemu to nieuniknione skutki uboczne). Niektóre języki funkcjonalne mogą być przystosowane do wykonywania wielu, jeśli nie wszystkich operacji obiektowych. Nie muszą się wzajemnie wykluczać, chociaż niektóre języki mają ograniczenia (np. Nie zezwalające na aktualizację zmiennych), które uniemożliwiają określone wzorce (jak zmienne pola).
Dla mnie najbardziej użytecznymi częściami programowania obiektowego są ukrywanie danych (enkapsulacja), traktowanie wystarczająco podobnych obiektów jako takich samych (polimorfizm) oraz gromadzenie danych i metod, które działają na tych danych razem (obiekty / klasy). Dziedziczenie może być okrętem flagowym OOP, ale dla mnie jest to najmniej ważna i najmniej używana część.
Najbardziej przydatne części programowania funkcjonalnego to niezmienność (tokeny / wartości zamiast zmiennych), funkcje (bez skutków ubocznych) i zamknięcia.
Nie sądzę, że jest zorientowany obiektowo, ale muszę powiedzieć, że jedną z najbardziej przydatnych rzeczy w informatyce jest możliwość deklarowania interfejsu, a następnie posiadania różnych funkcji i danych implementujących ten interfejs. Lubię też mieć kilka zmiennych danych do pracy, więc wydaje mi się, że nie czuję się całkowicie komfortowo w wyłącznie funkcjonalnych językach, chociaż staram się ograniczać zmienność i efekty uboczne we wszystkich projektach mojego programu.