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):
passInstanciando a classe B pra ver o que acontece:
>>> b = B()
estou na classe AOu 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 BMas 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 AAtençã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 'morrendo........'Testando…
>>> a = A()
nascendo...
>>> del a
morrendo........
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not definedO 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.....