Construtores e Destrutores em Python e PHP 5

  • Publicado em: 14/03/2008 02:41h
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 class 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? Ai 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 'morrendo........'

Testando...

>>> a = A()
nascendo...
>>> del a
morrendo........
>>> a
Traceback (most recent call last):
File "", line 1, in
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.....
  • Categorias: Python, PHP |
  • Por: Igor Sobreira |
  • 6 comentários

Comentários

Carlos André Ferrari [http://www.ferrari.eti.br]

Muito semelhantes mesmo, não abro mão dessas linguagens devido ao seu poder. as pessoas que as criticam ou são mal programadores ou são mal acostumados com coisas mascaradas. é muito comum encontrar um desenvolvedor de ".net" por exemplo, que não tem ideia de como funciona uma requisição http ou um upload de arquivos.

  • Adicionado em: 15/03/2008 22:26h

Flávio Ribeiro [http://www.flavioribeiro.com]

muito bom. :)

  • Adicionado em: 19/03/2008 18:53h

eduardo willians [http://pycappuccino.blogspot.com]

Muito bom, gostei.

  • Adicionado em: 19/03/2008 20:15h

Felipe Ribeiro [http://feliperibeiro.com]

E aí está uma diferença para o Java, já que lá o construtor da super classe é sempre chamado, recursivamente até chegar no construtor de Object :P

  • Adicionado em: 25/03/2008 23:10h

Helder

Fala cara!

Só confirmando: Construtores de destrutores são recursos que fazem parte do conceito de classe da Orientação a Objetos. Ou seja, você está certo! Construtores/destrutores tem exatamente a mesma função nas diversas linguagens OO. O que muda, no geral, é apenas a sintaxe de cada linguagem.

Parabéns pelo site!

  • Adicionado em: 03/06/2008 10:11h

Henrique [http://hcalves.com]

Eu gosto mais da sintaxe antiga para chamar o construtor parente:

A.__init__(self)

Me parece mais explícito: de A, chame o __init__

Apesar de achar a instaxe mais feia, entendo porque foi criado o builtin super()

super(B, self).__init__()

Nesse caso, não precisamos saber de antemão quem é o parente de B, super() retorna isso pra gente.

Legal o post Igor!

  • Adicionado em: 21/09/2008 07:27h

Adicione um Comentário

Nome
Email (não será mostrado)
Site
Comentário Você pode usar as tags <a href="">, <b>, <u> <i>