Dlaczego są one tak przydatne?

Jako programista oo, może mam trudności z widzeniem jego wartości. Jaką wartość dodaną dają? Czy pasują do świata OO?

Author: Peter Mortensen, 2009-08-20

10 answers

Zamknięcia nie dają dodatkowej mocy.

Wszystko, co można osiągnąć z nimi, można osiągnąć bez nich.

Ale są one bardzo przydatne do uczynienia kodu bardziej przejrzystym i czytelnym. A jak wszyscy wiemy, czysty czytelny krótki kod to kod, który jest łatwiejszy do debugowania i zawiera mniej błędów.

Dam ci krótki przykład Javy możliwego użycia:

    button.addActionListener(new ActionListener() {
        @Override public void actionPerformed(ActionEvent e) {
            System.out.println("Pressed");
        }
    });

Zostałoby zastąpione (gdyby Java miała zamknięcia) przez:

button.addActionListener( { System.out.println("Pressed"); } );
 28
Author: Gregory Mostizky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-20 11:44:33

Można to postrzegać jako uogólnienie klasy.

Twoja klasa ma jakiś stan. Ma kilka zmiennych członkowskich, które jego metody mogą używać.

Zamknięcie jest po prostu wygodniejszym sposobem na nadanie funkcji dostępu do stanu lokalnego.

Zamiast tworzyć klasę, która wie o zmiennej lokalnej, którą chcesz użyć funkcji, możesz po prostu zdefiniować funkcję na miejscu, i może ona pośrednio uzyskać dostęp do każdej zmiennej, która jest aktualnie widoczna.

Kiedy zdefiniuj metodę prętową w tradycyjnym języku OOP, jej zamknięciem jest "wszystkie pręty widoczne w tej klasie".

Języki z obsługą" właściwego "zamknięcia po prostu uogólniają to, więc zamknięcie funkcji jest "wszystkimi zmiennymi widocznymi tutaj". Jeśli" here " jest klasą, to masz tradycyjną metodę klasową.

Jeśli " here " znajduje się wewnątrz innej funkcji, to masz to, co programiści funkcjonalni uważają za zamknięcie. Twoja funkcja może teraz uzyskać dostęp do wszystkiego, co było widoczne w funkcji rodzica.

Jest to więc tylko uogólnienie, usuwające głupie ograniczenie, że "funkcje mogą być definiowane tylko wewnątrz klas", ale utrzymujące ideę, że "funkcje mogą widzieć dowolne zmienne widoczne w punkcie, w którym są zadeklarowane".

 64
Author: jalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-20 12:00:48

Dla mnie największą zaletą zamykania jest to, że piszesz kod, który uruchamia zadanie, pozostawia zadanie do uruchomienia i określa, co powinno się stać, gdy zadanie zostanie wykonane. Generalnie kod uruchamiany na końcu zadania wymaga dostępu do danych, które są dostępne na początku, a zamknięcie tego ułatwia.

Na przykład, powszechnym zastosowaniem w JavaScript jest uruchomienie żądania HTTP. Ktokolwiek to zaczyna, pewnie chce kontrolować, co się stanie, gdy nadejdzie odpowiedź. Więc zrobisz coś takiego:

function sendRequest() {
  var requestID = "123";
  Ext.Ajax.request({
    url:'/myUrl'
    success: function(response) {
      alert("Request " + requestID + " returned");
    }
  });
}

Z powodu zamknięcia JavaScript, zmienna "requestID" jest przechwytywana wewnątrz funkcji success. Pokazuje to, w jaki sposób można pisać funkcje żądania i odpowiedzi w tym samym miejscu i współdzielić zmienne między nimi. Bez zamknięcia należy przekazać requestID jako argument lub utworzyć obiekt zawierający requestID i funkcję.

 28
Author: JW.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-09 23:29:49

IMHO sprowadza się to do możliwości przechwytywania bloków kodu i ich kontekstu, które zostaną odwołane w pewnym momencie później i wykonane, gdy/jeśli/zgodnie z wymaganiami.

Mogą nie wydawać się wielką sprawą, a zamknięcia na pewno nie są czymś, czego potrzebujesz, aby robić rzeczy na co dzień - ale mogą sprawić, że kod będzie dużo prostszy i czystszy w pisaniu/zarządzaniu.

[przykładowy kod edycji na podstawie komentarza powyżej]

Java:

List<Integer> numbers = ...;
List<Integer> positives = new LinkedList<Integer>();
for (Integer number : integers) {
    if (number >= 0) {
        positives.add(number);
    }
}

Scala (pomijając niektóre z innych niuansów, takich jak typ wnioskowania i wildcards, więc porównujemy tylko efekt zamknięcia):

val numbers:List[Int] = ...
val positives:List[Int] = numbers.filter(i:Int => i >= 0)
 5
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-20 12:04:20

Szkoda, ludzie nie uczą się już Smalltalk w edu; tam zamknięcia są używane do struktur kontrolnych, wywołań zwrotnych, wyliczania kolekcji, obsługi wyjątków i innych. Poniżej znajduje się wątek obsługi czynności kolejki roboczej (w Smalltalku):

|actionQueue|

actionQueue := SharedQueue new.
[
    [
        |a|

        a := actionQueue next.
        a value.
    ] loop
] fork.

actionQueue add: [ Stdout show: 1000 factorial ].

I dla tych, którzy nie potrafią odczytać Smalltalka, to samo w składni JavaScript:

var actionQueue;

actionQueue = new SharedQueue;
function () {
    for (;;) {
        var a;

        a = actionQueue.next();
        a();
    };
}.fork();

actionQueue.add( function () { Stdout.show( 1000.factorial()); });

(cóż, jak widzisz: składnia pomaga w odczytaniu kodu)

Edit: zauważ, jak actionQueue jest odwołany z wnętrza bloki, które działają nawet dla rozwidlonego wątku-blok. To sprawia, że zamknięcia są tak łatwe w użyciu.

 4
Author: blabla999,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-24 08:45:52

Oto kilka ciekawych artykułów:

 3
Author: Jesper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-20 11:47:52

Zamknięcia pasują całkiem dobrze do świata OO.

Jako przykład, rozważmy C# 3.0: ma zamknięcia i wiele innych aspektów funkcjonalnych, ale nadal jest bardzo zorientowanym obiektowo językiem.

Z mojego doświadczenia wynika, że funkcjonalne aspekty C# mają tendencję do pozostania w implementacji członków klasy, a nie tyle jako część publicznego API moje obiekty kończą się ujawnieniem.

Jako takie, stosowanie zamknięć zazwyczaj jest szczegółami implementacji w inaczej zorientowanych obiektowo kod.

Używam ich cały czas, jak pokazuje fragment kodu z jednego z naszych testów jednostkowych (przeciwko Moq ):

var typeName = configuration.GetType().AssemblyQualifiedName;

var activationServiceMock = new Mock<ActivationService>();
activationServiceMock.Setup(s => s.CreateInstance<SerializableConfigurationSection>(typeName)).Returns(configuration).Verifiable();

Trudno byłoby określić wartość wejściową (nazwę typową) jako część pozornego oczekiwania, gdyby nie Funkcja zamykania C#.

 3
Author: Mark Seemann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-09 22:48:42

Co do kończącego się zapytania: "czy (zamknięcia) pasują do świata OO?"

W wielu językach zamknięcia, wraz z pierwszorzędnymi funkcjami, stanowią podstawę do tworzenia programów oo: przychodzą na myśl Javascript, Lua i Perl.

W innym bardziej "tradycyjnym" języku oo, z którym jestem zaznajomiony, Java, istnieją 2 podstawowe różnice:

  1. funkcje są Nie konstruktami klasy pierwszej
  2. w Javie szczegóły implementacji OO (czy zamknięcia są używane wewnętrznie) nie jest bezpośrednio narażone na działanie dewelopera, jak to jest w Javascript, Lua i Perl

Dlatego w" tradycyjnym języku OO", takim jak Java, dodawanie zamknięć jest w dużej mierze cukrem składniowym.

 0
Author: George Jempty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-07 18:32:00

Być może w świecie programowania skompilowanego korzyści z zamknięć są mniej zauważalne. W JavaScript zamknięcia są niezwykle potężne. Jest to z dwóch powodów:

1) JavaScript jest językiem interpretowanym, więc wydajność instrukcji i zachowanie przestrzeni nazw są niezwykle ważne dla szybszego i bardziej responsywnego wykonywania z dużych programów lub programów, które oceniają duże ilości danych wejściowych.

2) JavaScript jest językiem lambda. Oznacza to w funkcjach JavaScript są obiektami pierwszej klasy, które definiują zakres i zakres z funkcji rodzica jest dostępny dla obiektów potomnych. Jest to ważne, ponieważ zmienna może być zadeklarowana w funkcji nadrzędnej, używana w funkcji potomnej i zachowuje wartość nawet po powrocie funkcji potomnej. Oznacza to, że zmienna może być wielokrotnie używana przez funkcję z wartością już zdefiniowaną przez ostatnią iterację tej funkcji.

W rezultacie zamknięcia są niezwykle wydajne i zapewniają doskonałą wydajność w JavaScript.

 -2
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-09 22:49:20

Patrząc na powyższe przykłady, Mogę dodać swój bit.

  • Doceniam styl, ukrywanie stanu i łączenie wyrazów, ale to nie wystarczy

  • Wiele można powiedzieć o prostym i jawnym kodzie

  • uważam, że Scala, Perl i niektóre inne języki typu Scheme są zaprojektowane tak, aby stworzyć rodzaj skrótu dla określonego sposobu myślenia przez projektanta języka lub uczynić je "bardziej produktywnymi"

Wziąłbym prostotę Pythona i wczesna składnia Javy itp jako lepszy sposób na prostotę i klarowność

Może być dość szybko napisać tajemnicze zamknięcia łańcuchowe w ciasnej przestrzeni. jednak wszystko można zrobić za pomocą prostych obiektów i algorytmów

Zamknięcia są potrzebne, ale nie tak często, aby zagwarantować im bycie obywatelem pierwszej klasy .

 -2
Author: sdsadsadsada,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-05 09:51:25