[se...e mentali] Chiamate alle classi

Sì, in effetti è proprio un arnese da falegname mentale, anche perché l'implementazione che ho usato funge, quindi perché chiedere? Bé ma per capire no?

Ecco il fatto: ho implementato una serie di classi che fanno determinate cose, nell'applicazione principale le richiamo col solito metodo della funzioncina _autoload e funziona.

Quello che mi chiedo è perché  :crazy:

Mi spiego meglio: il metodo da me usato usa una variabile per instanziare le classi chiamata con molta fantasia $obj, ebbene una volta le faccio instanziare la classe Presentazione e la seconda volta la classe chiamata Button.

Tra le due chiamate manco che so un __destruction, ho usato sempre la stessa variabile e funziona.

Ecco l'esempio per capirci meglio (spero)

<?php

function __autoload ($className) {
    $fileName = './class/'.strtolower($className).'.class.php';
    $status = (@include_once $fileName);
       
    if ($status === false) {
        echo "errori nella classe: $className in $fileName";
    }  
}
$pageController = 'Presentazione';
try {
  $obj = new $pageController();
  $form = new Button();
} catch (Project_Exception_AutoLoad $e) {
    header('HTTP/1.0 404 Not Found');
    printf('<h1>Not Found</h1><p>The requested page %s was not found on this server.</p><hr /><em>$id$</em>', $_SERVER['REQUEST_URI']);
}

$pageController = 'Button';
try {
  $obj = new $pageController();
  echo $obj->btnReset('class="cancella"');
} catch (Project_Exception_AutoLoad $e) {
    header('HTTP/1.0 404 Not Found');
    printf('<h1>Not Found</h1><p>The requested page %s was not found on this server.</p><hr /><em>$id$</em>', $_SERVER['REQUEST_URI']);
}
?>
</body>
</html>

In pratica ripeto il costrutto try catch e do a $obj prima Presentazione e poi Button e da qui richiamo pure un metodo, sempre tramite $obj. Se l'avessi fatti in Pascal mi avrebbero fucilato, ma qui funge alla grande.

Perché?  :dunno:

Sto pure pensando di mettere utto dentro una funzioncina pern on ripetere sempre le stesse cose  :rm_shifty:

inviato 9 anni fa
Marco Grazia
modificato 9 anni fa
X 0 X

PHP è un linguaggio di scripting, quindi non viene mai compilato. Neanche durante l'esecuzione viene realmente compilato quindi le sue istruzioni non si traducono in codice macchina ma in comandi per l'interprete PHP (lo Zend Engine II).

Per questa ragione è possibile fare con PHP cose che un linguaggio compilato non potrebbe fare, poiché il compilatore per produrre le istruzioni macchina ha bisogno di sapere a priori cosa succederà a runtime.

In PHP invece puoi mettere delle istruzioni che a runtime possono concretizzarsi in operazioni assolutamente inpredicibili, senza che questo sia un problema. Inoltre il PHP ha elevato questa dinamicità ai massimi livelli slegando le variabili dai tipi di dato impiegati internamente, sempre a runtime. In altre parole quando scriviamo il codice possiamo ignorare la tipizzazione dei dati poiché questi vengono decisi a runtime e non dal codice stesso, come avviene ad esempio in C o in Java.

Per una variabile presente in uno script PHP (nel codice) non è possibile dire a priori cosa conterrà o a quale oggetto farà riferimento.

Uno script PHP è solo una ricetta che viene letta al momento della sua esecuzione dall'interprete PHP ed eseguita. E' l'interprete PHP a fare i miracoli, allocando e deallocando risorse, in modo da realizzare quello che lo sviluppatore ha specificato nello script.

Un programma compilato invece è "solo" davanti al sistema operativo, quindi non può contare su un "cervello" del tipo dello Zend Engine II

Questa forte connotazione dinamica di PHP ne determina da un lato la sua forza, dall'altro è spesso un limite poiché la libertà tende ad abbassare il rigore ed il controllo sulla bontà del codice.

 :bye:

risposto 9 anni fa
Gianni Tomasicchio
X 0 X

Perfettamente d'accordo, ma allora come mai nelle classi si comincia a parlare tipizzazione?

Prendi le costanti, secondo PHP const inserito in una classe sarebbe una tipizzazione mi suona strano e francamente lo trovo fuorviante.

Inoltre e comunque se le cose stanno come hai detto, e anche leggendo sul manuale in proposito dei costruttori di una classe, sembrerebbe che sia presente comunque una specie di garbage collection o meglio, di un garbage (fogna) dove vanno a finire le cavolate come quella che intenzionalmente ho eseguito io.

Concordo solo col fatto che $obj è una semplice variabile che contiene prima un valore (Presenza) e poi un altro (Button) e qui scusa ma mi sorge un dubbio.

Dalla mia piccolissima esperienza, un oggetto una volta instanziato rimane comunque da qualche parte in memoria, quindi anche se $obj prima contiene il "valore" Presenza, al momento in cui viene instanziato Button e passato a $obj, Presenza che fine fa?

Il mio dubbio è che rimanga in qualche modo parcheggiato in memoria, d'altra parte se no perché preoccuparsi da parte di PHP (degli sviluppatori di PHP intendo) per creare oltre che ad un costruttore, di un distruttore della classe instanziata.

Magari, non saprei nemmeno come distruggere una classe instanziata, tu ne sai qualcosa?

risposto 9 anni fa
Marco Grazia
X 0 X

E mi sono andato a guardare il manuale del PHP riguardo a distructor e parrebbe da quanto leggo che:

Destructor

void __destruct ( void )

PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++. The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed.

Ovvero: "when the object is explicitly destroyed.  - quando l'oggetto sarà esplicitamente distrutto" (?) cioè se chiamo __destructor() per una classe, questa sarà esplicitamente distrutta? Naaaa, mi sa piuttosto he passando da una classe all'altra come ho fatto io, quando viene instanziata una classe esplicitamente sarà distrutta quella prima  :buck: oggi provo a fare una cosa: creare un metodo di prova per la classe Presentazione, chiamarlo, e poi dopo aver instanziato la Button, provare a richiamare il metodo di quella prima.

Se mi manda a quel paese, allora è vero, la classe precedente è stata distrutta esplicitamente, così come pure esplicitamente viene costruita quando esiste il metodo __constructor dentro la classe, se invece mi richiama l'oggetto della classe prima allora è un casino orribile.

Mentre scrivo, sto pensando che forse, bisogna inserire un metodo __destruction() esplicitamente dentro la classe perché essa venga effettivamente distrutta, così come viene "costruita" se dentro c'è il metodo __construct(), ora vedo se trovo qualcosa di tangibile online e poi torno a scrivere.

risposto 9 anni fa
Marco Grazia
X 0 X

Rieccomi, ci ho messo poco in effetti :)

L'esempio l'avevo sotto gli occhi:

Esempio 19-7. Destructor Example

<?php
class MyDestructableClass {
   function __construct() {
       print "In constructor\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "Destroying " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();
?> 

$obj chiama la classe MyDestructableClass() che si autoinstanzia e auto distrugge subito dopo.

E d'altra parte leggendo le note degli utenti, proprio la prima di esse fa un esemio bellissimo e complicato, su come si instanzia una classe, come la si traccia e come si distrugge la stessa.

Però per farlo, la registra: register_shutdown_function("example::destructors");, registrando proprio la classe che chiamerà una funzione che a cascata distrugge tutte le instanze create della classe:

public static function destructors() {
        foreach ( example::$OBJS as $obj )
            $obj->destruct();
    }
private function destruct() {
        if ( isset(example::$OBJS[$this->id]) )
            unset(example::$OBJS[$this->id]);
    }

una volta che si è chiamato il metodo pubblico destructors, questo richiama ricorsivamente tutti gli elementi dell'array $OBJS e li passa al metodo destruct che se li trova, li passa ad unset per la rimozione.

Ok è un sistema complesso, però il tipo che l'ha creato, dice chiaramente che per la normale programmazione on ha senso, ma che il senso lo ha quando si parla di CMS o roba ancora più complessa.

Alla fine dell'esempio dice anche che crede di aver reso le idde di tutti un poco più confuse.

Concordo con lui a pieno :)

Eppure qualcosa mi fa frullare in testa, ovvero una classe in grado di istanziare oggetti dentro un array.

Il suo esempio instanzia proprio un array ($OBJS) di oggetti, e quando viene richiamato alla fine, altro non fa che distruggere questi oggetti.

Questo è il suo esempio completo:

<?php

class example {

    public static $OBJS = array();
    public $id;
    
    public function __construct() {
        example::$OBJS[] = $this;
    # I actually use a 'lastKey' routine here, but in this example the following should work:
        $this->id = key( array_slice(example::$OBJS, count(example::$OBJS) -1, 1, true) );
    }
    
    public function __destruct() {
        $this->close();
    }
    
# unset the tracked object
    private function destruct() {
        if ( isset(example::$OBJS[$this->id]) )
            unset(example::$OBJS[$this->id]);
    }
    
# public shutdown routine
    public function close() {
        if ( isset($this->destructed) )
            return;
    # ...
        $this->destruct();
        $this->destructed = true;
    }
    
# static class method to destruct all objects
    public static function destructors() {
        foreach ( example::$OBJS as $obj )
            $obj->destruct();
    }

}

# register a shutdown function which triggers before destructors (hence when such results are desired for a Session class, etc)
    register_shutdown_function("example::destructors");

?>

dice chiaramente che non ha testato il codice, ha solo riscritto una funzione che ha usato in un suo framework, ma a me pare insteressante.

Gianni a te cosa sembra?  ::)

risposto 9 anni fa
Marco Grazia
X 0 X

E' una follia... rispondo alle prime domante:

come mai nelle classi si comincia a parlare tipizzazione?

Perché nei linguaggi ad oggetti definire una classe equivale a definire un tipo e le variabili che contengono un determinato oggetto devono essere di quel tipo. Anche in PHP5 le classi determinano un tipo, ma come tutti i tipi di php, questi vengono gestiti internamente dallo Zend Engine quindi in maniera trasparente allo script.

Prendi le costanti, secondo PHP const inserito in una classe sarebbe una tipizzazione mi suona strano e francamente lo trovo fuorviante.

Una costante pone vincoli sul valore, non sul tipo.

Inoltre e comunque se le cose stanno come hai detto, e anche leggendo sul manuale in proposito dei costruttori di una classe, sembrerebbe che sia presente comunque una specie di garbage collection o meglio, di un garbage (fogna) dove vanno a finire le cavolate come quella che intenzionalmente ho eseguito io.

Si, a differenza di linguaggi come il C++, il PHP (ma anche il Java e altri) non abbandonano il codice al suo destino durante la sua esecuzione ma il sistema di runtime (lo Zend Engine per il PHP, la JRE per il Java) controlla l'uso delle risorse allocate (come gli oggetti istanziati) e al momento opportuno recupera la memoria occupata ad esempio da oggetti ormai irragiungibili dal programma.

La possibilità di creare oggetti e renderli inaccessibili a causa del codice scritto male è un problema piuttosto diffuso che prende il nome di "memory leakage". Il C e il C++ non hanno un sistema per risolvere nativamente questo problema mentre il PHP (e altri) contengono degli algoritmi (ad esempio il reference count) che permettono di individuare gli oggetti abbandonati nel limbo dallo sviluppatore e li eliminano quando serve spazio. Questa pulizia non viene fatta ripetutamente poiché richiede l'esecuzione di questi algoritmi che possono risultare onerosi (se ti interessa approfondisco). Ecco perché non puoi mai sapere quando viene lanciato il distruttore di questi oggetti.

Dalla mia piccolissima esperienza, un oggetto una volta istanziato rimane comunque da qualche parte in memoria, quindi anche se $obj prima contiene il "valore" Presenza, al momento in cui viene instanziato Button e passato a $obj, Presenza che fine fa?

Rimane in memoria fino a quando PHP non ha la necessità di fare pulizia

Il mio dubbio è che rimanga in qualche modo parcheggiato in memoria, d'altra parte se no perché preoccuparsi da parte di PHP (degli sviluppatori di PHP intendo) per creare oltre che ad un costruttore, di un distruttore della classe instanziata.

Il distruttore è un regalo per lo sviluppatore, non serve al PHP. Il distruttore permette allo sviluppatore di fare qualche pulizia che il PHP non sarebbe stato in grado di compiere automaticamente.

Magari, non saprei nemmeno come distruggere una classe instanziata, tu ne sai qualcosa?

unset($oggetto);

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

Cerco di fare il punto della situazione:

- quando si istanzia un oggetto viene allocato in memoria dello spazio per contenere un particolare TIPO di dato. L'indirizzo di memoria viene conservato dalla variabile che punta all'oggetto. Si parla quindi di variabile che contiene un reference ad un oggetto. Ecco perché in PHP5 gli oggetti vengono passati per riferimento.

- il PHP tiene traccia delle variabili che puntano a quell'oggetto

- quando il PHP lo ritiene opportuno, effettua un controllo sugli oggetti che non vengono puntati da nessuna variabile e li distrugge

- Conviene distruggere qualsiasi oggetto non appena si è certi che questo non servirà più. Questo in realtà è valido per qualsiasi risorsa. Non bisogna lasciare al garbage collector di PHP questo compito.

 :bye:

risposto 9 anni fa
Gianni Tomasicchio
X 0 X

Quindi due punti sono venuti a galla in questa discussione, che non puoi sapere come il PHP gestirà le risorse della macchina su cui gira, e che tu programmatore, non ci puoi fare nulla in merito.

Se ho capito bene, gli oggetti sono dichiarati in memoria come statici ed appartengono alla grande famiglia degli array i quali vengono giustappunto cancellati con unset() però da quanto hai detto tu in altre parti del discorso, non si può distruggere un oggetto, o forse ho capito male io e in realtà il discorso che hai fatto vale se io non lo distruggo implicitamente.

Quello che mi fa andare in palla è che ragionado, si evince che costruendo un'applicazione in PHP, non potendo sapere quante risorse macchina hai a disposizione hai al momento in cui lo script girerà, non puoi neppure sapere se e quando lo script andrà in blocco.

risposto 9 anni fa
Marco Grazia
X 0 X
Quindi due punti sono venuti a galla in questa discussione, che non puoi sapere come il PHP gestirà le risorse della macchina su cui gira...

Vero

... e che tu programmatore, non ci puoi fare nulla in merito.

Puoi eliminare le risorse inutili con unset()

Se ho capito bene, gli oggetti sono dichiarati in memoria come statici ed appartengono alla grande famiglia degli array i quali vengono giustappunto cancellati con unset() però da quanto hai detto tu in altre parti del discorso, non si può distruggere un oggetto, o forse ho capito male io e in realtà il discorso che hai fatto vale se io non lo distruggo implicitamente.

Statici in che senzo? unset() cancella qualsiasi variabile, indipendentemente dal suo contenuto (stringa, intero, array, elemento di un array, oggetto).

Il Garbage Collector agisce ovviamente solo sugli oggetti "persi nel limbo della memoria".

Quello che mi fa andare in palla è che ragionado, si evince che costruendo un'applicazione in PHP, non potendo sapere quante risorse macchina hai a disposizione hai al momento in cui lo script girerà, non puoi neppure sapere se e quando lo script andrà in blocco.

Si, però puoi scoprire quanta ram mangia la tua applicazione e porre questo quantitativo come requisito di sistema (come fanno tutti i software)

 :bye:

risposto 9 anni fa
Gianni Tomasicchio
X 0 X

Ehm e come si fa a sapere quanta memoria sta mangiando? Prove a runtime?

E un'altra cosa: cosa mi conviene fare, ovvero come mi conviene implementare una serie di oggetti da chiamarsi ciclicamente.

Mi spiego meglio: sto costruendo un framework come ne esistono già in asp.net, ovvero, sto costruendo una serie di oggetti che permettono di creare pezzi di una pagina web come se fossero dei mattoni.

Questo fa sì che ad esempio un oggetto "Button" può essere o no implementato (se in una pagina ho bisogno di un form poso aver bisogno di un bottone, ma non solo; in un form non necessariamente ci devono essere tutti gli oggetti previsti per un form: textbox, checkbox, bottoni e altro).

L'idea è quella di creare una serie di classi eventualmente da estendere, che so una classe Form che si estende a sotto classi Textbox, Button, eccetera.

In un caso del genere tu che tipo di approccio terresti? Io stavo pensando ad un approccio di tipo factoring. E non è tutto :( ma una cosa alla volta.

risposto 9 anni fa
Marco Grazia
X 0 X

per sapere quanta memoria viene allocata da PHP si usa memory_get_usage()

Un Form HA UN Bottone, HA UNA Textbox.

Nella modellazione ad oggetti la relazione HA UN si realizza creando degli attributi Bottone e Textbox nella classe proprietaria Form.

Poiché non sai a priori quanti elementi avrai nel form allora crei un attributo di tipo Array di elementi del form.

 :bye:

risposto 9 anni fa
Gianni Tomasicchio
X 0 X
per sapere quanta memoria viene allocata da PHP si usa memory_get_usage()

denghiu

Un Form HA UN Bottone, HA UNA Textbox.

non ho capito il senso di quegli HA UN, non c'è dubbio che un form può avere una sola textbox e un solo bottone o addirittura uno solo di essi, ma il forum con cui ti sto scrivendo, ad esempio, ha sicuramente una textbox, una selectbox, diversi bottoni, una textarea, tre checkbox e altri due bottoni.

Nella modellazione ad oggetti la relazione HA UN si realizza creando degli attributi Bottone e Textbox nella classe proprietaria Form.

Poiché non sai a priori quanti elementi avrai nel form allora crei un attributo di tipo Array di elementi del form.

 :bye:

Allora ci siamo.

Siccome ho intenzione di creare un piccolo (?) framework che creerà nelle intenzioni un form, e dato che i componenti stessi del form saranno implementati come oggetti del form stesso, mi chiedo se è conveniente creare un array di oggetti. Magari con un pattern factory o qualcosa del genere.

risposto 9 anni fa
Marco Grazia
X 0 X

Si, ti conviene creare un array di oggetti.

 :bye:

risposto 9 anni fa
Gianni Tomasicchio
X 0 X

Ottimo, allora ci sono quasi.

Ho altre richieste più mirate ma non so dove porle, ora ci penso e poi apro un altro thread.

risposto 9 anni fa
Marco Grazia
X 0 X
Effettua l'accesso o registrati per rispondere a questa domanda