Frage

In JavaScript verschachtelte Funktionen sind sehr nützlich:Verschlüsse, private Methoden und was haben Sie..

Was sind verschachtelte PHP-Funktionen für?Wer Sie benutzt und wofür?

Hier eine kleine Untersuchung, die ich habe

<?php
function outer( $msg ) {
    function inner( $msg ) {
        echo 'inner: '.$msg.' ';
    }
    echo 'outer: '.$msg.' ';
    inner( $msg );
}

inner( 'test1' );  // Fatal error:  Call to undefined function inner()
outer( 'test2' );  // outer: test2 inner: test2
inner( 'test3' );  // inner: test3
outer( 'test4' );  // Fatal error:  Cannot redeclare inner()
War es hilfreich?

Lösung

Es ist nichts im Grunde, habe ich immer behandelt, das als eine Nebenwirkung der parser.

Eran Galperin ist falsch, dass diese Funktionen sind irgendwie privat, Sie sind einfach nicht deklarierte bis outer() ausgeführt wird.Sie sind auch nicht privat scoped, Sie tun polute globalen Bereich, wenn auch verzögert.Und als Rückruf der äußeren Rückruf könnte nur noch einmal aufgerufen werden.Ich verstehe immer noch nicht, wie das ist hilfreich anwenden es auf ein array, welches sehr wahrscheinlich ruft die alias-mehr als einmal.

Die einzige "Reale Welt" - Beispiel, ich könnte Graben ist diese kann nur einmal ausgeführt und könnte umgeschrieben werden-Reiniger IMO.

Die einzige Verwendung, die ich denken kann, ist für Module, Anruf [name]_include Methode setzt mehrere verschachtelte Methoden im globalen Raum, kombiniert mit

if (!function_exists ('somefunc')) {
  function somefunc() { }
}

überprüft.

PHP OOP wäre natürlich die bessere Wahl :)

Andere Tipps

Wenn Sie mit PHP 5.3 können Sie mehr Javacript artiges Verhalten mit einer anonymen Funktion bekommen:

<?php
function outer() {
    $inner=function() {
        echo "test\n";
    };

    $inner();
}

outer();
outer();

inner(); //PHP Fatal error:  Call to undefined function inner()
$inner(); //PHP Fatal error:  Function name must be a string
?>

Ausgabe:

test
test

[Rewritten nach dem Kommentar von @PierredeLESPINAY.]

Es ist nicht nur ein Nebeneffekt überhaupt, aber eigentlich eine sehr nützliche Funktion für dynamisch modifiziert die Logik des Programms. Es ist von dem Verfahren PHP Tagen, kann aber auch mit OO Architekturen nützlich sein, wenn Sie möglichen alternativen Implementierungen für bestimmte eigenständige Funktionen in dem direkteste Weg zur Verfügung stellen mögen. (Während OO die bessere Wahl die meiste Zeit, es ist eine Option, kein Mandat, und einige einfache Aufgaben brauchen nicht die zusätzliche cruft.)

Zum Beispiel, wenn Sie dynamisch / bedingt Plugins aus dem Rahmen laden, und wollen das Leben der Plugin-Autoren super einfach zu machen, Sie Standardimplementierungen für einige kritische Funktionen bereitstellen kann das Plugin überschreiben nicht:

<?php // Some framework module

function provide_defaults()
{
    // Make sure a critical function exists:
    if (!function_exists("tedious_plugin_callback"))
    {
        function tedious_plugin_callback()
        {
        // Complex code no plugin author ever bothers to customize... ;)
        }
    }
}

Funktionen innerhalb von Funktionen definiert Ich kann nicht für viel Gebrauch, sondern bedingt definierte Funktionen sehen ich kann. Zum Beispiel:

if ($language == 'en') {
  function cmp($a, $b) { /* sort by English word order */ }
} else if ($language == 'de') {
  function cmp($a, $b) { /* sort by German word order; yes it's different */ }
} // etc

Und dann Ihren Code tun muss, ist verwenden, um die ‚cmp‘ Funktion in Dinge wie usort () ruft so tun Sie nicht Streu Sprache überprüft alle über Ihren Code. Nun habe ich nicht getan, aber ich kann Argument sehen, es zu tun.

Alle oben gesagt, könnte man einfach eine verschachtelte Funktion erstellen einen lokalisierte, ich wiederholenden Code innerhalb einer Funktion zu ersetzen (das wird nur innerhalb der übergeordneten Funktion verwendet werden). Eine anonyme Funktion ist ein perfektes Beispiel dafür.

Man könnte sagen, nur private Methoden erstellen (oder kleinere Codeblocks) in einer Klasse, aber das ist muddying das Wasser, wenn eine ultra-spezifische Aufgabe (die die Mutter exklusiv) muss modularisiert werden, aber nicht notwendigerweise zur Verfügung der Rest einer Klasse. Die gute Nachricht ist, wenn es sich herausstellt, dass Sie diese Funktion benötigen Sie woanders, das Update ist ziemlich elementar (die Definition einer zentraleren Position verschieben).

Im Allgemeinen mit Hilfe von JavaScript als Standard, mit der anderen C basierte Programmiersprachen bewerten ist eine schlechte Idee. JavaScript ist auf jeden Fall ein eigenes Tier im Vergleich zu PHP, Python, Perl, C, C ++ und Java. Natürlich gibt es viele allgemeine Ähnlichkeiten, aber die Nitty, kiesige Details (Referenz JavaScript: The Definitive Guide, 6. Auflage, Kapitel 1-12 ), wenn sie darauf geachtet, Kern JavaScript einzigartig zu machen, schön, unterschiedlich, einfach und komplex alle gleichzeitig an. Das ist meine zwei Cent.

Just klar sein, ich sage nicht, verschachtelte Funktionen sind privat. Nur, dass Verschachtelung kann Unordnung vermeiden helfen, wenn etwas triviale Bedürfnisse modularisiert werden (und werden nur von der übergeordneten Funktion erforderlich).

All meine PHP ist OO, aber ich habe eine Verwendung für verschachtelte Funktionen sehen, vor allem, wenn Ihre Funktion rekursiv ist und nicht unbedingt ein Objekt. Das heißt, es nicht außerhalb der Funktion aufgerufen werden sie verschachtelt ist in, aber ist rekursiv und muss anschließend eine Funktion sein.

Es gibt wenig Sinn, ein neues Verfahren für die ausdrückliche Verwendung eines einzigen anderen Verfahrens zu machen. Für mich ist das ungeschickte Code und sorten nicht der Punkt der OO. Wenn du gehst nie irgendwo anders, diese Funktion zu nennen, nisten sie.

In webservice Berufung fanden wir es eine viel geringere Overhead (Speicher und Geschwindigkeit), die dynamisch in einer verschachtelten Art und Weise, einzelne Funktionen über Bibliotheken voller 1000s Funktionen. Der typische Call-Stack könnte tief nur zwischen 5-10 Anrufe sein erfordert die Verknüpfung ein Dutzend 1-2kb Dateien dynamisch besser war als Megabyte inklusive. Dies wurde getan, nur durch eine kleine util Funktion Verpackung erfordert zu schaffen. Die enthaltenen Funktionen werden verschachtelten innerhalb der Funktionen über den Call-Stack. Betrachten Sie es im Gegensatz zu Klassen voll von 100s von Funktionen, die nicht bei jedem Webservice Aufruf erforderlich waren, könnte aber auch die eingebauten verzögertes Laden Funktionen von PHP verwendet.

Ich weiß, dass dies eine alte Post, aber FWIW ich verschachtelte Funktionen verwenden, um einen sauber und ordentlich Ansatz zu einem rekursiven Aufruf zu geben, wenn ich nur die Funktionalität lokal benötigen - zum Beispiel für den Aufbau hierarchischer Objekte usw. (natürlich müssen Sie die übergeordnete Funktion vorsichtig sein, nur einmal aufgerufen wird):

function main() {
    // Some code

    function addChildren ($parentVar) {
        // Do something
        if ($needsGrandChildren) addChildren ($childVar);
    }
    addChildren ($mainVar); // This call must be below nested func

    // Some more code
}

Ein Punkt beachten in PHP verglichen mit JS zum Beispiel ist, dass der Anruf an die verschachtelten Funktion nach gemacht werden muss, das heißt unterhalb, die Funktionsdeklaration (im Vergleich mit JS, wo der Aufruf der Funktion eines beliebigen Stelle innerhalb der übergeordneten Funktion sein kann

, wenn Sie in PHP sind 7 dann sehen: Diese Implementierung wird Ihnen eine klare Vorstellung über verschachtelte Funktion. Angenommen, wir haben drei Funktionen (zu (), boo () und Zoo ()) verschachtelt in Funktion foo (). boo () und Zoo () haben gleichnamige verschachtelte Funktion xoo (). Jetzt in diesem Code habe ich klar die Regeln der verschachtelten Funktionen Kommentar gesetzt.

   function foo(){
        echo 'foo() is called'.'<br>';
        function too(){
            echo 'foo()->too() is called'.'<br>';
        }
        function boo(){
            echo 'foo()->boo() is called'.'<br>';
            function xoo(){
                echo 'foo()->boo()->xoo() is called'.'<br>';
            }
            function moo(){
                echo 'foo()->boo()->moo() is called'.'<br>';
            }
        }
        function zoo(){
            echo 'foo()->zoo() is called'.'<br>';
            function xoo(){     //same name as used in boo()->xoo();
                echo 'zoo()->xoo() is called'.'<br>';
            }
        #we can use same name for nested function more than once 
        #but we can not call more than one of the parent function
        }
    }

/****************************************************************
 * TO CALL A INNER FUNCTION YOU MUST CALL OUTER FUNCTIONS FIRST *
 ****************************************************************/
    #xoo();//error: as we have to declare foo() first as xoo() is nested in foo()

    function test1(){
        echo '<b>test1:</b><br>';
        foo(); //call foo()
        too();
        boo();
        too(); // we can can a function twice
        moo(); // moo() can be called as we have already called boo() and foo()
        xoo(); // xoo() can be called as we have already called boo() and foo()
        #zoo(); re-declaration error
        //we cannont call zoo() because we have already called boo() and both of them have same named nested function xoo()
    }

    function test2(){
        echo '<b>test2:</b><br>';
        foo(); //call foo()
        too();
        #moo(); 
        //we can not call moo() as the parent function boo() is not yet called
        zoo(); 
        xoo();
        #boo(); re-declaration error
        //we cannont call boo() because we have already called zoo() and both of them have same named nested function xoo()

    }

Nun, wenn wir nennen test1 () die Ausgabe dieser sein wird:

test1:
foo() is called
foo()->too() is called
foo()->boo() is called
foo()->too() is called
foo()->boo()->moo() is called
foo()->boo()->xoo() is called

Wenn wir nennen test2 () die Ausgabe wird folgendermaßen aus:

test2:
foo() is called
foo()->too() is called
foo()->zoo() is called
zoo()->xoo() is called

Aber wir können beide text1 nicht () aufrufen und test2 () bei gleichzeitig Neudeklaration Fehler zu vermeiden

Ich habe nur wirklich diese Eigenschaft verwendet, wenn es sinnvoll ist, eine kleine rekursive Funktion in einem primären auszuführen, kategorischere Funktion, aber wollte es nicht auf eine andere Datei bewegen, weil sie auf das Verhalten eines primären fundamentale waren Prozess. Ich weiß, es gibt auch andere „best practice“ Wege dies zu tun, aber ich möchte sicherstellen, dass meine Devs diese Funktion sehen jedes Mal, wenn sie an meinem Parser aussehen, ist es wahrscheinlich, was sie sowieso ändern sollte ...

Verschachtelte Funktionen nützlich sind, in memoization (Caching-Funktion der Performance-Ergebnisse zu verbessern).

<?php
function foo($arg1, $arg2) {
    $cacheKey = "foo($arg1, $arg2)";
    if (! getCachedValue($cacheKey)) {
        function _foo($arg1, $arg2) {
            // whatever
            return $result;
        }
        $result = _foo($arg1, $arg2);
        setCachedValue($cacheKey, $result);
    }
    return getCachedValue($cacheKey);
}
?>

Verschachtelte Funktionen nützlich sind, wenn Sie die verschachtelte Funktion wollen eine Variable verwenden, die innerhalb der übergeordneten Funktion deklariert wurde.

<?php
ParentFunc();
function ParentFunc()
{
  $var = 5;
  function NestedFunc()
  {
    global $var;
    $var = $var + 5;
    return $var;
  };
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
}
?>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top