2010-07-30 13 views
8

Jakie są plusy i minusy zamknięć klas i viceversa?Jaka jest różnica między zamknięciami i klasami tradycyjnymi?

Edytuj: Jak to ujął użytkownik Faisal, zarówno zamknięcia, jak i klasy mogą być użyte do "opisania obiektu, który utrzymuje i manipuluje stanem", więc zamknięcia umożliwiają programowanie w sposób zorientowany obiektowo przy użyciu języków funkcjonalnych. Jak większość programistów, jestem bardziej zaznajomiony z klasami.

Intencją tego pytania nie jest otwarcie kolejnej wojny o płomienie, która ma lepszy paradygmat programowania, czy zamknięcia i klasy są w pełni ekwiwalentne, czy też biednych ludzi.

Chciałbym wiedzieć, czy ktoś znalazł scenariusz, w którym jedno podejście naprawdę bije drugie i dlaczego.

+1

Udzielanie odpowiedzi w sposób nieobowiązujący język jest bardzo, bardzo trudne, ponieważ najwygodniejszy z nich jest prawie koniecznie określony przez język, którego używasz. – zneak

Odpowiedz

9

Funkcjonalnie zamknięcia i obiekty są równoważne. Zamknięcie może emulować obiekt i na odwrót. Więc to, którego używasz, to kwestia syntaktycznej wygody lub tego, z którym językiem programowania najlepiej sobie poradzisz.

W C++ zamknięcia nie są dostępne w postaci syntaktycznej, więc jesteś zmuszony korzystać z "funktorów", które są obiektami, które zastępują operator() i mogą być wywoływane w sposób, który wygląda jak wywołanie funkcji.

W Javie nie masz nawet funktorów, więc dostajesz takie rzeczy jak wzorzec Odwiedzający, który byłby po prostu funkcją wyższego rzędu w języku obsługującym zamknięcia.

W standardowym schemacie nie masz obiektów, więc czasami kończysz je realizując pisząc zamknięcie z funkcją wysyłki, wykonując różne pod-zamknięcia w zależności od parametrów przychodzących.

W języku takim jak Python, którego składnia ma zarówno funktory, jak i zamknięcia, jest to w zasadzie kwestia gustu, która jest lepszym sposobem wyrażania tego, co robisz.

Osobiście chciałbym powiedzieć, że w każdym języku, który ma składnię dla obu, zamknięcia są o wiele bardziej przejrzystym i czystszym sposobem wyrażania obiektów za pomocą jednej metody. I odwrotnie, jeśli twoje zamknięcie zaczyna obsługiwać wysyłkę do pod-zamknięć w oparciu o przychodzące parametry, prawdopodobnie powinieneś używać obiektu zamiast tego.

2

Zamknięcia są bardzo lekko związane z zajęciami. Klasy umożliwiają definiowanie pól i metod, a zamknięcia zawierają informacje o zmiennych lokalnych z wywołania funkcji. Nie ma żadnego możliwego porównania tych dwóch w sposób agnostyczny językowo: nie służą one w ogóle temu celowi. Poza tym zamknięcia są dużo bardziej związane z programowaniem funkcjonalnym niż z programowaniem obiektowym.

Na przykład, spójrz na następujący kod C#:

static void Main(String[] args) 
{ 
    int i = 4; 
    var myDelegate = delegate() 
    { 
     i = 5; 
    } 

    Console.WriteLine(i); 
    myDelegate(); 
    Console.WriteLine(i); 
} 

Daje to "4", a następnie "5". myDelegate, będąc delegatem, jest zamknięciem i wie o wszystkich zmiennych aktualnie używanych przez funkcję. Dlatego też, gdy go nazywam, dozwolona jest zmiana wartości iwewnątrz funkcji "nadrzędnej". Nie byłoby to dozwolone dla normalnej funkcji.

Klasy, jeśli wiesz, czym są, są zupełnie inne.

Możliwym powodem twojego zamieszania jest to, że gdy język nie ma obsługi języka dla zamknięć, można symulować je za pomocą klas, które będą zawierać każdą zmienną, którą musimy zachować. Na przykład, możemy przepisać powyższy kod tak:

class MainClosure() 
{ 
    public int i; 

    void Apply() 
    { 
     i = 5; 
    } 
} 

static void Main(String[] args) 
{ 
    MainClosure closure; 
    closure.i = 4; 

    Console.WriteLine(closure.i); 
    closure.Apply(); 
    Console.WriteLine(closure.i); 
} 

Mamy przekształcił delegate do klasy, że mamy o nazwie MainClosure. Zamiast tworzyć zmienną i wewnątrz funkcji , utworzyliśmy obiekt MainClosure, który ma pole i. To ta, której użyjemy. Zbudowaliśmy również kod funkcji wykonywany wewnątrz metody instancji, zamiast wewnątrz metody.

Jak widać, mimo że był to łatwy przykład (tylko jedna zmienna), jest to znacznie więcej pracy. W kontekście, w którym chcesz zamknąć, używanie obiektów jest złym rozwiązaniem. Klasy są jednak użyteczne nie tylko do tworzenia zamknięć, a ich zwykły cel jest zwykle inny.

+1

Myślałem o tym samym, ale wydaje się, że debatuje się raczej nad tym, czy zamknięcia lub przedmioty są bardziej wyraziste. Pozwólcie, że dam wam odrobinę posmakowania w dyskusji: http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html – Faisal

+0

Zgodnie z moim rozumowaniem, można zaimplementować obiekty za pomocą zamknięć i można symulować zamknięcia do punktu za pomocą obiektów. Jednak obiekty zwykle nie przechwytują automatycznie lokalnego środowiska, więc trzeba je jawnie zainicjować ... Ale @zneak jest poprawny: ostatecznie służą one dwóm różnym celom, a ich życzenie nie jest nieuzasadnione. – Amadan

+0

@Faisal: Sądzę, że ta debata dotyczy jawnie używania zamknięć a tworzenia klasy symulującej zamknięcie, w którym to przypadku zamknięcie "pełnoprawne" jest oczywiście wygodniejsze. – zneak

4

Osobiście uważam, że jest to kwestia wykorzystania odpowiedniego narzędzia do pracy ... a konkretniej do właściwego komunikowania swoich intencji.

Jeśli chcesz jawnie pokazać, że wszystkie twoje obiekty mają wspólną definicję i chcesz ich silnego sprawdzenia, prawdopodobnie chcesz użyć klasy. Wada polegająca na tym, że nie można zmienić struktury twojej klasy w czasie wykonywania, jest w tym przypadku prawdziwą siłą, ponieważ dokładnie wiesz, z czym masz do czynienia.

Jeśli zamiast tego chcesz utworzyć heterogeniczną kolekcję "obiektów" (tj. Stan reprezentowany jako zmienne zamknięte pod pewną funkcją w/wewnętrznymi funkcjami służącymi do manipulowania tymi danymi), lepiej będzie, jeśli stworzysz zamknięcie. W tym przypadku nie ma prawdziwej gwarancji co do struktury obiektu, z którego korzystasz, ale masz pełną swobodę definiowania go dokładnie tak, jak chcesz w czasie wykonywania.

Dziękuję za pytanie, właściwie; Odpowiedziałem na coś w rodzaju "nieudolnych" klas i zamknięć są zupełnie inne! na pierwszy rzut oka, ale z pewnymi badaniami zdaję sobie sprawę, że problem nie jest tak bliski i suchy, jak myślałem.

+0

Innymi słowy, zamknięcia jako obiekty są bardziej jak * interfejsy * w większości języków OOP - reprezentacja wewnętrzna jest całkowicie ukryta, a wszystko, co zapewnia takie same publiczne metody, może zostać zamienione. Niektórzy ludzie uważają, że jest to lepszy styl OOP , zabawnie ... –

Powiązane problemy