-+  Associazione
-+  Documenti
-+  Eventi
-+  Community
-+  Blog
-+  Link

Ottobre 2013

Dom Lun Mar Mer Gio Ven Sab
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

Cerca






 

« Libri, che passione! | Home | ICJ, impressioni »

Objective C... in Perl
10.10.04

Sull'ultimo numero di TPJ ho letto, e trovato piuttosto interessante, un articolo su ObjectivePerl. Questo modulo permette di utilizzare la sintassi di Objective C (o almeno qualcosa che le somigli) nella definizione e nell'utilizzo degli oggetti in Perl. Di fatto altro non è un wrapper che converte la sintassi ObjectivePerl in quella standard Perl.

In effetti, ed ora penso verrò fucilato, ho sempre trovato un po' bizzarra la sintassi dell'OOP in Perl, soprattutto per quanto concerne le variabili d'istanza e la definizione delle classi stesse. Per quanto io non sappia praticamente nulla di Objective C (e, da quanto ho visto, è un peccato) , ho cercato di utilizzare questo modulo. Mi è anche uscito fuori un po' di codice.

#!/usr/local/bin/perl

use strict;
use ObjectivePerl;

@implementation Strega
{
    @private: $anni;
    @protected: $grido;
}

+ new {
    return ~[$super new];
}

- anni {
    return $anni;
}

- grida {
    return $grido;
}

- setGrido: $sGrido {
    $grido = $sGrido;
}

+ info {
    return "Sono una strega!";
}

@end

La classe viene definita con @implementation, e subito sotto ad essa si possono indicare le variabili d'istanza, che possono essere private o protette: questa è una simpatica novità rispetto alla sintassi standard di Perl, che non permette delle vere e proprie variabili d'istanza, ma obbligata all'utilizzo di qualcosa tipo $self->{'grido'}.

Un'altra novità è rapprentata dalla possibilità di definire sia metodi statici che metodi d'istanza: i primi si definiscono utilizzano +, i secondi servendosi di -.

Ho anche scritto una classe Amelia, figlia della Strega appena definita:

@implementation Amelia : Strega
{
    @protected: $pianto;
}

- piangi {
    return $pianto;
}

- setPianto: $sPianto {
    $pianto = $sPianto;
}

+ info {
    return "Voglio derubare Zio Paperone!";
}

@end

Anche per quanto riguarda l'ereditarietà la sintassi è dunque piuttosto chiara e lineare, in perfetto stile Objective C. Ecco invece il codice che utilizza le classi sopra definite:

# Crea una strega
my $st = ~[Strega new];
~[$st setGrido: "He he he"];
print ~[$st  grida]."\n";
# Crea Amelia
my $am = ~[Amelia new];
~[$am setPianto: "Sniff!"];
print ~[$am  piangi]."\n";

Al di là della diversa sintassi, c'è una variazioni fondamentale rispetto a Perl standard: vengono utilizzati i messaggi anziché le chiamate ai metodi. Ciò crea alcune differenze: un oggetto può rispondere oppure no ad un messaggio, e chiaramente se viene inviato un messaggio non esistente non accade nulla. Cioè, utilizzando la sintassi Objective Perl, non viene sollevato alcun errore se si chiama un metodo inesistente.

Secondo l'autore di ObjectivePerl, l'overhead del modulo è molto basso, ed il suo utilizzo non mina dunque le performance dei propri programmi. In futuro verranno aggiunte altre cose, quali i protocols, ed il livello di visibilità (pubblico, privato, protetto) anche per i moduli.

Personalmente, trovo un tantino scomodo che quanto segue non funzioni:

@implementation Sasso
{
    @protected: $minerale;
}

+ new {
    my $self = ~[$super new];
    $minerale = "Basalto";
    return $self;
}

L'assegnazione di $minerale dà errore, poiché le variabili d'istanza non risultano accessibili dal costruttore, nemmeno dopo aver inizializzato la classe genitore.

Penso che ci studierò ancora un po' sopra, vediamo cosa ne esce. Leggendo la draft di questo articolo, Larsen mi ha fatto inoltre notare che sarebbe interessante mostrare nel dettaglio come i costrutti linguistici dell'Objective C assenti in Perl vengono resi grazie a questo modulo. Visto che io di Objective C non so molto (leggi: non so nulla), magari qualcuno vuole fornire il suo contributo... ;-)

Inviato da arthas il 10.10.04 23:55
Ti è piaciuto questo articolo? Iscriviti al feed!

Inviato da dada il 13.10.04 12:32

arthas, il tuo post è molto interessante e mi riprometto di studiarmi un po' meglio ObjectivePerl e Objective C. intanto, però, ti rispondo su una cosa, ossia quello che tu trovi scomodo che non funzioni.

in primis, new è definito come metodo statico, quindi è giusto che non possa accedere alle variabili d'istanza. sarebbe una violazione della protezione se così non fosse.

in secundis, dopo aver inizializzato il genitore (anche se nel tuo esempio non mi sembra che Sasso derivi da nulla, ma probabilmente ogni oggetto deriverà implicitamente da una classe base, non so) devi richiamare un metodo su quell'oggetto. infatti ho provato il seguente codice e sembra funzionare:

@implementation Sasso {
  @protected: $minerale;
}
- setMinerale: $sMinerale {
  $minerale = $sMinerale;
}
+ new {
  my $self = ~[$super new];
  ~[$self setMinerale: "Basalto"];
  return $self;
}

cheers,

Aldo

Inviato da arthas il 13.10.04 13:18

OPS, mi ero del tutto fatto sfuggire lasciato sfuggire il questione del self. ;-) In effetti anche in Objective C devo indicare:

[self setMinerale: "Basalto"];

Ciò che mi ha confuso era il fatto che in Ojective C è possibile quanto segue:

@interface Sasso: NSObject {
    char* minerale;
}
@end

@implementation Sasso
-(Minerale*) init {
    self = [super init];
    minerale = "Basalto";
    return self;
}
@end

Invece, in Perl la stessa cosa non è accettata, anche utilizzando un costruttore non statico, come indicato di seguito:

@implementation Sasso
{
    @protected: $minerale;
}

- new {
    my $self = ~[$super new];
    $minerale = "Basalto";     # Errore
    return $self;
}

L'errore riportato è:



Can't use string ("Testclass") as a HASH ref while "strict refs" in use at /usr/local/lib/perl5/site_perl/5.8.5/ObjectivePerl/InstanceVariable.pm line 31.


Bisogna quindi definire ed utilizzare il metodo setMinerale, come mi hai indicato tu. Suppongo sia anche la soluzione più corretta per quanto riguarda l'Objective C...


Mandi, Michele.

Inviato da Kyle Dawkins il 18.10.04 22:11

Sorry, I don't speak Italian but it seems you're having trouble with some ObjectivePerl... I just wanted to say that this:

- new {
my $self = ~[$super new];
$minerale = "Basalto"; # Errore
return $self;
}

should really be

+ new {
my $self = ~[$super new];
$minerale = "Basalto"; # Errore
return $self;
}

because the constructor is actually a class method, not an instance method. If you don't specify it as a class method, then $className never gets defined and your object won't be instantiated.

Thanks!

Kyle

Inviato da arthas il 19.10.04 00:49

Hi Kyle!

thanks for taking the time to view this blog entry. The real problem is that the code which seems correct, that is the one you post:

+ new {
    my $self = ~[$super new];
    $minerale = "Basalto";     # Error
    return $self;
}

does not work. The following error is reported.

Global symbol "$minerale" requires explicit package name at prova.pl line XX.
BEGIN not safe after errors--compilation aborted at prova.pl line YY.

It seems that instance variables are unavailable inside the constructor. This, as dada pointed out, it an expected behaviour. It's, however, different than in Objective C.

Michele.










Devo ricordare i dati personali?






D:
Sull'autore...
D:
La ML di Perl.it
Iscriviti! mongers@lists.perl.it è la lista ufficiale di Perl Mongers Italia per porre quesiti di tipo tecnico, per rimanere aggiornato su meeting, incontri, manifestazioni e novità su Perl.it.
D:
Annunci Google