Extendendo dinamicamente uma classe
Alguém pode dizer: "Tenha cada função em um arquivo separado" - até aí, tudo bem - "e inclua estes arquivos quando forem necessários.".
Mas isto não resolve meu problema, pois ao incluir um arquivo, seja dentro ou fora da classe, esta função não será incorporada à classe, mas aberta ao script todo.
Codificando o parágrafo anterior:
Executando o código:
Neste caso, a minha função no arquivo "bar.php", estará aberta para qualquer classe e função do código, e eu precisarei passar como variável (referência) o objeto:
Sendo a função bar definida como:
Essa forma funciona até certo ponto, mas gera alguns problemas:
1. Se já houver uma outra função chamada "bar", retornará erro.
2. Algumas funções deverão ser chamadas por "$foo->funcao()" e outras somente por "funcao()". Confusão...
Algumas soluções:
1. Basta ter um controle para verificar a existência da função antes de carregá-la.
2. Não se importar com funções externas à classe.
O que eu quero mostrar, é que existe uma maneira de resolver o meu caso inicial sem estas complicações.
Mas isto não resolve meu problema, pois ao incluir um arquivo, seja dentro ou fora da classe, esta função não será incorporada à classe, mas aberta ao script todo.
Codificando o parágrafo anterior:
<?php class foo { var $value=1; function plugin($nome_plugin) { include "/caminho/ate/os/plugins/" . $nome_plugin . ".php"; } } ?>
Executando o código:
<?php $foo = new foo; $foo->plugin('bar'); // incluirá o arquivo "bar.php" ?>
Neste caso, a minha função no arquivo "bar.php", estará aberta para qualquer classe e função do código, e eu precisarei passar como variável (referência) o objeto:
<?php bar($foo,3); ?>
Sendo a função bar definida como:
<?php // bar.php function bar(&$obj, $soma){ $obj->value = $obj->value + $soma; } ?>
Essa forma funciona até certo ponto, mas gera alguns problemas:
1. Se já houver uma outra função chamada "bar", retornará erro.
2. Algumas funções deverão ser chamadas por "$foo->funcao()" e outras somente por "funcao()". Confusão...
Algumas soluções:
1. Basta ter um controle para verificar a existência da função antes de carregá-la.
2. Não se importar com funções externas à classe.
O que eu quero mostrar, é que existe uma maneira de resolver o meu caso inicial sem estas complicações.
Realmente Hugo isto acontece. Percebi outro dia no meu projeto. Uma forma de corrigir isso aí é copiando todas as variáveis da classe na nova extendida:
<?php
// Função "extend" da classe "foo"
function extend($codigo) {
$nome_classe = get_class($this);
srand((double)microtime()*1000000);
$nome_nova_classe = $nome_classe . rand(0,99);
eval('class '. $nome_nova_classe .' extends '. $nome_classe .' { '. $codigo .' }');
$obj = new $nome_nova_classe();
$vars = get_class_vars($nome_classe);
foreach($vars AS $key=>$value) {
$obj->$key = &$this->$key;
}
$this = $obj;
unset($obj);
}
?>
<?php
// Função "extend" da classe "foo"
function extend($codigo) {
$nome_classe = get_class($this);
srand((double)microtime()*1000000);
$nome_nova_classe = $nome_classe . rand(0,99);
eval('class '. $nome_nova_classe .' extends '. $nome_classe .' { '. $codigo .' }');
$obj = new $nome_nova_classe();
$vars = get_class_vars($nome_classe);
foreach($vars AS $key=>$value) {
$obj->$key = &$this->$key;
}
$this = $obj;
unset($obj);
}
?>
14/12/2003 2:06pm
(~21 anos atrás)
Qdo vc carregar o plugin vc vai perder todos os atributos da classe não? sendo obrigado a carregar o plugin antes de mecher em qualquer coisa da classe....
14/12/2003 1:17pm
(~21 anos atrás)
Muito bem lembrado Eduardo. Nem tinha me tocado disso.
Uma maneira de corrigir isso é substituir a linha da função 'extend':
$nome_nova_classe = $nome_classe . "_ext";
por:
srand((double)microtime()*1000000);
$nome_nova_classe = $nome_classe . rand(0,999);
A probabilidade de redeclarar uma classe cai bastante usando esse código.
Uma maneira de corrigir isso é substituir a linha da função 'extend':
$nome_nova_classe = $nome_classe . "_ext";
por:
srand((double)microtime()*1000000);
$nome_nova_classe = $nome_classe . rand(0,999);
A probabilidade de redeclarar uma classe cai bastante usando esse código.
21/11/2003 2:00pm
(~21 anos atrás)
Ocorre um problema junto ao codigo explicado: quando eu tenho diversos objetos que de uma mesma classe e crio dinamicamente esta extensão ele emitira um erro dizendo que no pode redeclarar a classe, sendo necessario ( julgo melhor ).. alterar em vez de *_ext ser *_(nome do objeto )...
Abraços
Abraços
21/11/2003 1:04pm
(~21 anos atrás)
explicou direitinho sim.. entendi
fica bem dinâmico e interessante de se trabalhar deste jeito que você falou
tem algum grande projeto que você desenvolveu baseando-se neste esquema proposto no artigo ?
fica bem dinâmico e interessante de se trabalhar deste jeito que você falou
tem algum grande projeto que você desenvolveu baseando-se neste esquema proposto no artigo ?
18/11/2003 11:47am
(~21 anos atrás)
Olha, no fundo é isso que a função 'extend' está fazendo usando eval(). Vou tentar explicar a vantagem.
Do jeito que você está falando, para usar a função 'foo_foo_foo', você tem que criar um objeto assim:
<?php
$myfoo = new myfoo;
?>
O jeito que eu estou propondo é concentar tudo na classe base (ou "brain" como você chamou =) ).
<?php
$foo = new foo;
$foo->plugin('myfoo');
$foo->foo_foo_foo();
?>
Aqui não vemos muitas vantagens, mas se tivermos mais plugins? Do jeito que você está falando:
<?php
$myfoo = new myfoo;
$yourfoo = new yourfoo;
$ourfoo = new ourfoo;
// ...
?>
Ou seja, preciso ter diversos objetos individuais para cada plugin.
Se usar a função 'plugin':
<?php
$foo = new foo; // base
$foo->plugin('myfoo');
$foo->plugin('yourfoo');
$foo->plugin('ourfoo');
?>
Você tem disponível todas os plugins no mesmo objeto $foo. Não é legal? =)
Realmente eu sei que o PEAR, e outras clases funcionam deste jeito que você falou. Mas num projeto recente eu vi vantagem de usar tal método.
A explicação que eu vejo para o PEAR usar desta maneira é que as classes que extendem a base PEAR são grandes e completas, com grande número de funções. Assim, você utilizará somente a nova classe que extende PEAR.
Em se tratando de um grande número de funções extras que você queira incorporar, onde em um script você precisa somente de certo plugin e em outro um plugin diferente, chamar dinamicamente tais funções, individualmente, é, ao meu ver, uma vantagem.
Neste caso seriam diversas funções que tem propósitos diferentes e que não tem relação umas com as outras, não havendo vantagem em juntar em uma classe única que extende a base.
Espero que tenha explicado meu ponto de vista. =)
Um abraço!
Do jeito que você está falando, para usar a função 'foo_foo_foo', você tem que criar um objeto assim:
<?php
$myfoo = new myfoo;
?>
O jeito que eu estou propondo é concentar tudo na classe base (ou "brain" como você chamou =) ).
<?php
$foo = new foo;
$foo->plugin('myfoo');
$foo->foo_foo_foo();
?>
Aqui não vemos muitas vantagens, mas se tivermos mais plugins? Do jeito que você está falando:
<?php
$myfoo = new myfoo;
$yourfoo = new yourfoo;
$ourfoo = new ourfoo;
// ...
?>
Ou seja, preciso ter diversos objetos individuais para cada plugin.
Se usar a função 'plugin':
<?php
$foo = new foo; // base
$foo->plugin('myfoo');
$foo->plugin('yourfoo');
$foo->plugin('ourfoo');
?>
Você tem disponível todas os plugins no mesmo objeto $foo. Não é legal? =)
Realmente eu sei que o PEAR, e outras clases funcionam deste jeito que você falou. Mas num projeto recente eu vi vantagem de usar tal método.
A explicação que eu vejo para o PEAR usar desta maneira é que as classes que extendem a base PEAR são grandes e completas, com grande número de funções. Assim, você utilizará somente a nova classe que extende PEAR.
Em se tratando de um grande número de funções extras que você queira incorporar, onde em um script você precisa somente de certo plugin e em outro um plugin diferente, chamar dinamicamente tais funções, individualmente, é, ao meu ver, uma vantagem.
Neste caso seriam diversas funções que tem propósitos diferentes e que não tem relação umas com as outras, não havendo vantagem em juntar em uma classe única que extende a base.
Espero que tenha explicado meu ponto de vista. =)
Um abraço!
18/11/2003 10:37am
(~21 anos atrás)
cara, seu artigo é muito legal, só que
eu estava vendo o padrão da pear e algumas classes que estou usando, e reparei o seguinte:
há um arquivo PEAR.php com a classe
e como você disse para não "sujar" muito a classe com coisas desnecessarias cria-se o "brain" do negocio que fica nesse arquivo ai..
e um novo codigo é feito num outro arquivo php
foo.php
com uma classe
<?php
class myfoo extends PEAR {
function foo_foo_foo
}
?>
dai você trabalha chamando o PEAR.php
e eventualmente os teus packages né..
tuas subclasses, teus features sei lá.. nomeação é o que não falta..
mas seria uma outra forma de estar trabalhando não ?
bom, é isso!
Abraços!
eu estava vendo o padrão da pear e algumas classes que estou usando, e reparei o seguinte:
há um arquivo PEAR.php com a classe
e como você disse para não "sujar" muito a classe com coisas desnecessarias cria-se o "brain" do negocio que fica nesse arquivo ai..
e um novo codigo é feito num outro arquivo php
foo.php
com uma classe
<?php
class myfoo extends PEAR {
function foo_foo_foo
}
?>
dai você trabalha chamando o PEAR.php
e eventualmente os teus packages né..
tuas subclasses, teus features sei lá.. nomeação é o que não falta..
mas seria uma outra forma de estar trabalhando não ?
bom, é isso!
Abraços!
17/11/2003 7:22pm
(~21 anos atrás)
Bom, se você não entende porque nao vê vantagens veja um outro artigo (hehe, sem propagandas) do André de Castro Zorzo que fala sobre classes no PHP também.
Espero ter ajudado
Espero ter ajudado
17/11/2003 7:16pm
(~21 anos atrás)
Valeu ae.. eu não aprendo muito bem as classes por que não consigo enxergar realmente a vantagem de utilizá-las. :).
Vou ver se dou uma lida sobre isso por aí! Valeu a ajuda!
Vou ver se dou uma lida sobre isso por aí! Valeu a ajuda!
17/11/2003 6:37am
(~21 anos atrás)
O JavaScript abaixo não roda através do navegador Firefox. Será que VC poderia me ajudar alterando algum(s) parâmetro(s) ? Agradeço desde já = Fiumari:
<script language="JavaScript"> var ultimo=-1, dBanner;
function carrega(x) {dBanner=x;Banners()}
function Banners()
{ var MNews = new Array();
MNews[0]= '<iframe " name="_blank" scrolling="no" src="http://www.finet.com.br/google.htm" width="100%" frameborder="0" target="_blank" height="350" BORDER="0"></iframe><a href="http://www.finet.com.br/google.htm" target="_blank"></a>';
MNews[1]= '<iframe " name="_blank" scrolling="no" src="http://www.finet.com.br/google2.htm" width="100%" frameborder="0" target="_blank" height="350" BORDER="0"></iframe><a href="http://www.finet.com.br/google2.htm" target="_blank"></a>'
while((Numero = parseInt(Math.random()*MNews.length))==ultimo);
dBanner.innerHTML=MNews[Numero];
setTimeout("Banners()",15000);
} </script>