PHP undeclare?

bpblub

Cadet 4th Year
Registriert
Mai 2008
Beiträge
124
Hallo Leute,

Ich hab folgendes Problem:

test1.php:

PHP:
class test{
...
}

test2.php:

PHP:
class test{
...
}

Und ich habe eine php-Datei, wo ich beide Klassen iterativ brauche und aufrufe. Gibt es eine Möglichkeit, wenn man z.B. test1.php einbindet, die zu dedeklarieren um somit die test2.php zu benutzen?
Leider kann ich in test1.php und test2.php die Klassennamen nicht verändern.

Vielen Dank für eure Hilfe.

Liebe Grüße,
bpblub.
 
wieso kannst du den namen der klassen nicht ändern?

naja egal, was du brauchst ist ein state Pattern.

d.h. du schriebst dir eine abstrakte klasse, die enthält dann ein Objekt der Klasse Test und leitet alle methoden aufrufe einfach weiter, du musst dann nur in der Abtrakten Klasse das Test Objekt austauschen.

Allerdings solltest du dir dein designe nochmal gründlich überlegen oder gucken ob du nicht voneinander erben lassen kannst
 
Hey,

Danke für eure Antworten. Ich werde mir mal eure Vorschläge antun. :)

naja egal, was du brauchst ist ein state Pattern.
Allerdings solltest du dir dein designe nochmal gründlich überlegen oder gucken ob du nicht voneinander erben lassen kannst

Das Problem ist einfach, dass es schön wäre, wenn ich es so hinbekommen würde. Ich brauche auch keine großartigen Funktionen aus den Klassen, sondern nur Variablen und Konstanten. Wenn es halt nicht mit den redeclaren oder undeclaren funktioniert, fande ich die Dateien an per file auseinander zu bauen. Es ist nicht so wichtig, wieso ich sie nicht umbenennen kann, es geht einfach nicht, wegen Arbeitsaufwand etc..

Nochmals danke für eure Antworten -- für die zukünftigen natürlich auch. :)

Liebe Grüße,
blub.
 
Warum kannst du wegen Arbeitsaufwand das nicht ändern? Erstellst du nicht einfach die Referenz zu einem Objekt? So ist es doch egal ob du

$test = new test();
$test->getProperty();

----------------

$test = new test();
$test->getAnotherProperty();


oder sowas machst

$test = new test();
$test->getProperty();

---------------------------------
$test = new test2();
$test->getAnotherProperty();
 
man kann in php nicht 2 mal die selbe klasse deklarieren.
da kommt ein fehler wie "Fatal error: canot redeclare Class 'Test'"
 
Erstes beispiel wirft ein Problem, aber beim 2. Wird ein Objekt einer anderen anderen klasse erzeugt (test2). Die referenz test bleibt aber. Falls es dabei probleme gibt einfach einmal $test = ""; machen?
 
aber er will ja den Klassen namen behalten. habe jetzt auch noch ein wenig gegoogelt, das scheint aber in PHP wirklich nicht zu gehen.
Man könnte natürlich bei jeder iteration ein neues script starten lassen, das je nach dem Test 1 oder Test 2 beinhalet, das wird aber super mega speicher aufwendig und vermutlich wird dir das script vor beenden verrecken.
Aber ich denke das man das mit einem wesntlich geschickteren Aufbau auch ander gelöst bekommt, könnest du vlt. ein wenig genauer beschreiben was du vorhast?

das mit dem arbeitsaufwand halte ich aber für ein gerücht. Moderne IDE's unterstützen dich beim refactoren, bzw. hier gezielt beim umbennen einer klasse ungemein. Und auch sonst würde ein einfaches STRG+H ja reichen.

ich glaube außerdem das du dir hier einen mehr aufwand machst, ich kann nicht so gut sehen wo der sinn in 2 klassen liegt die gleich heißen, bei jeder iteration aber getauscht werden müssen sehen.

Wie wäre es mit einer einzigen klasse test, die selber 2 Anonyme innere klassen (jetzt weiß ich gar nicht ob PHP das kann....) nuzt ?
Oder wenn das nicht geht, eine Klasse mit namen Test die ihrerseits dann 2 Attribute hat, nämlich Test1 und Test2.

So dann instanzierst du für die Iteration die Klasse Test.

und je nach änderung machst du dann $test->getTest1() oder $test->getTest2().

also quasi eine kapselung um eine kapselung.

deine API ist jedenfalls nicht gut durchdacht.

P.S.
@chriz: ich würde lieber $test = null; machen, sonst wird speicher für einen String reserviert ;)
oder gleich unset($test) um alles zu leeren.
 
Oder so ;) Aber selbst wenn der Speicher nur für einen String reserviert ist, kann man ein Objekt erzeugen ;) Oder sehe ich da falsch?
 
nein das ist richtig, php ist da ja sehr moderat. schei** schwache typisierung ^^
wenn man ein objekt auf null setzt weiß ich das der destructor aufgerufen und der speicher freigegeben wird, wenn man einfach nur auf einen string verweißt bin ich mir nicht sicher.
ich meine die 2 byte die ein leerstring benötigt tun auch nichts zur sache, aber man sollte sich angewohnen speicher komplett zu leeren ;)
 
Mercsen schrieb:
wenn man ein objekt auf null setzt weiß ich das der destructor aufgerufen und der speicher freigegeben wird, wenn man einfach nur auf einen string verweißt bin ich mir nicht sicher.
Der Destruktor muss auch nicht sofort aufgerufen werden, denn das macht immernoch der GC und wann der GC läuft kann der GC immernoch selbst entscheiden.

Mercsen schrieb:
ich meine die 2 byte die ein leerstring benötigt tun auch nichts zur sache, aber man sollte sich angewohnen speicher komplett zu leeren ;)
wird zum Ende des Scriptes, welches nur eine Hand voll Millisekunden läuft, doch sowieso autom. gelöscht, bzw. vom GC geholt wenn die Variable den Scope verlässt. Halte ich also für absolut unnötig, sofern man nicht gerade wirklich mit Daten arbeitet, die wirklich viel Arbeitsspeicher benötigen. Variablen zu löschen bläht den Code nur unnütz auf.
 
also dann würde ich vlt. nochmal richtig lesen, ok vlt. habe ichmich auch falsch ausgedrückt.
Ich wollte auf keinen Fall aussagen das man den Speicher immer leeren soll, nur wenn man es macht, dann sollte es richtig passieren.

zum php destructor:
http://www.php.net/manual/de/features.gc.refcounting-basics.php

das verstehe ich so, das wenn ich selber alle referenzen lösche, sofort der speicher gecleart wird, da der intere counter auf 0 springt, wieso dann dort nicht auch direkt den destructor aufrufen?

dazu mal folgendes script

PHP:
<?php

class gc {

    var $id;
    var $construct;
    var $destruct;

    public function  __construct($id) {
        $this->construct = microtime();
        $this->construct = explode(" ", $this->construct);
        $this->construct = $this->construct[0];
        $this->id = $id;


        echo "GC '$id' erzeugt um $this->construct<br>";
    }

    public function nope() {
        sleep(1);
    }

    public function  __destruct() {
        $this->destruct = microtime();
        $this->destruct = explode(" ", $this->destruct);
        $this->destruct = $this->destruct[0];
        echo "GC '$this->id' zerst&ouml;rt um $this->destruct<br>";
        echo "<hr>";
    }
}

$list = array();

for($i = 1; $i <= 100; $i++) {
    $list[$i] = new gc($i);
    if($i % 5 == 0){
        $destruct = microtime();
        $destruct = explode(" ", $destruct);
        $destruct = $destruct[0];
        echo "<hr>";
        echo "Unset um $destruct<br>";
        unset($list[$i]);
    }
}
?>

also entweder läuft der GC einfach die GANZE Zeit mit oder aber der container zval ruft bei 0 referenzen sofort den destructor auf.

was man auch ganz schön daran sieht das wirklich nach jeder 5. iteration ein destructor aufgerufen wird. Nach deiner ansicht müsste das ja dann irgendwo irgendwann im code passieren und dann gleich alle auf einmal, die keine referenz mehr haben.

wenn man die Zeiten vergelicht zeichnet sich ab das er im schnitt 500 ns braucht zwischen 2 operationen, fürs erzeugen wie fürs zerstören, kann mir nicht vorstellen das nach jeder instanzierung der GC drüber läuft.

wenn man das ganze ohne ausgaben oder den nervigen explode machen würde, sehe das ergbnis wohl noch eindeutiger aus, habe leider gerade keinen debugger zur hand in dem man den genauen ablauf untersuchen könnte.....

bei java hast du recht, da arbeitet der GC auf jedenfall so, aber ich meine mal gelesen zu haben das in php sofort der destructor aufgerufen wird wenn keine referenzen mehr da sind.

Lässt man in der schleife die zuweisung zu dem array raus wird sofort aufgerufen und zerstört.
 
Zuletzt bearbeitet:
Du hast natürlich Recht, dass in PHP aktuell der Destruktor sofort aufgerufen wird, ich hätte mich eventuell deutlicher ausdrücken müssen. Es ist aber ein Implementationsdetail und keine Garantie durch die Sprache, es kann sich also jederzeit ändern, wenn an der Implementierung geschraubt wird. Das beim Reference Counting bei einem Zählerstand von 0 aktuell das Objekt direkt gelöscht wird macht aber eben auch noch der GC, weil der GC dafür zuständig ist den Müll wegzuräumen. Dieser besteht eben meist aus Reference Counting und noch einer Erkennung von Zyklen, das Wegräumen bei einem Zählerstand von 0 beim Reference Counting ist aber eben nicht garantiert, das kann durchaus auch in einer späteren Version später passieren, wenn man feststellt, dass man dadurch an bestimmten Stellen effizientere Implementierungen machen kann.
Stichwort: Generational GC
 
Ich seh schon die Berufsschule holt mich ein. In Java haben wir die kurzliebigsten Objekte in die Young-Generation einsortiert.

Zeigen andere Programmiersprachen nicht bereits das andere Implementierungen mehr Sinn machen, als bei dem Counter von 0 "den Müll wegzuräumen"?

Ich denke in PHP werden wir aber nicht in "normalen" Webapplikationen (riesige Webshops etc bieten vielleicht eine ausnahme wenn ich mir den memoryverbrauch manchmal so anschaue) darauf achten müssen, wann der GC den destruktur aufruft. Wenn man das überhaupt macht und nicht objekte in "freier wildbahn links liegen lässt".
 
Zurück
Oben