Igor Sobreira

Construtores e Destrutores em Python e PHP 5

Estava aqui brincando com Orientação a Objetos no PHP 5, e não pude evitar uma comparação com Python. Percebi que os contrutores e destrutores funcionam praticamente da mesma maneira, provavelmente na maioria das linguagens deve ser assim.

Em Python o construtor é o método __init__ da sua classe. Bem, Mark Pilgrim, autor do Dive into Python tem uma opinião diferente:

"__init__ is called immediately after an instance of the class is created. It would be tempting but incorrect to call this the constructor of the class. It's tempting, because it looks like a constructor (by convention, __init__ is the first method defined for the class), acts like one (it's the first piece of code executed in a newly created instance of the class), and even sounds like one (“init” certainly suggests a constructor-ish nature). Incorrect, because the object has already been constructed by the time __init__ is called, and you already have a valid reference to the new instance of the class. But __init__ is the closest thing you're going to get to a constructor in Python, and it fills much the same role. "

Eu concordo com essa explicação, mas aqui vou chamar __init__ de construtor mesmo.

No Python funciona assim: você tem uma classe A, e uma classe B que herda de A. Se a class A tiver o método __init__, mas a classe B não tiver, ao se instanciar a classe B, o interpretador vai procurar o construtor, não achando na classe atual, vai subindo para as classes base, chamando o primeiro que encontrar, no caso o da classe A. Confuso? Vejamos em código...

class A(object):
    def init(self):
        print 'estou na classe A'

class B(A): pass

Instanciando a classe B pra ver o que acontece:

>>> b = B()
estou na classe A

Ou seja, como a classe B não tinha um construtor (__init__), o interpretador foi subindo para as classes base até achar um, e não precisou ir muito longe, a classe A já tinha.

Mas se definirmos o __init__ na classe B, ele vai ser executado e pára por ai:

class A(object):
    def init(self):
        print 'estou na classe A'

class B(A): def init(self): print 'estou na classe B'

E o resultado será

>>> b = B()
estou na classe B

Mas e se quisermos que o __init__ da classe A fosse executado também? Nesse caso precisariamos chamá-lo explicitamente. Isso pode ser feito com a função super()

class A(object):
    def init(self):
        print 'estou na classe A'

class B(A): def init(self): print 'estou na classe B' super(B, self).init()

E o resultado será como esperado

>>> b = B()
estou na classe B
estou na classe A

Atenção! Esse comportamento de construtores do Python acontece tanto para classes old style quanto para classes new style(que herdam de object). Porém o super() só funciona com classes new style. Uma sintaxe alternativa seria: A.__init__(self)

A mesma coisa acontece com PHP 5 e seu construtor, o __construct, vejamos o mesmo exemplo

class A {
    public function __construct() {
        echo "Estou na classe A";
    }
}
class B extends A { }

$b = new B;

A saída do código abaixo será:

Estou na classe A

Mas e se definirmos o __construct da classe B, como chamar o da class A também? Vejamos o exemplo:

class A {
    public function construct() {
        echo "Estou na classe A";
    }
}
class B extends A {
    public function construct() {
        parent::__construct();
        echo "Estou na classe B";
    }
}

$b = new B;

A saída será:

Estou na classe A
Estou na classe B

Em relação aos destrutores a idéia é a mesma. No Python seria o método __del__, e no PHP 5 o __destruct. Um exemplo com Python:

class A(object):
    def init(self):
        print 'nascendo...'

def __del__(self):
    print &#39;morrendo........&#39;</code></pre></figure>

Testando...

>>> a = A()
nascendo...
>>> del a
morrendo........
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

O mesmo exemplo em PHP:

class A {
    public function construct() {
        echo "Nascendo..";
    }
    public function destruct() {
        echo "Morrendo.....";
    }
}

$a = new A; unset($a);

E a saida será:

Nascendo..
Morrendo.....
blog comments powered by Disqus

My name is Igor Sobreira and is my website. I'm a software developer working at Real Geeks. I currently live in Hawaii doing the two things that I like most: windsurfing and writing software.

See more about me and get in touch.