Para esse exercício, faremos um encapsulamento com a classe Pessoa, uma agregação entre essa classe e a classe Livro, e uma interface. Veja o diagrama abaixo:
Pessoa |
---|
- nome - idade - sexo |
+ fazerAniver() |
Livro |
---|
- titulo - autor - totPaginas - pagAtual - aberto - leitor |
+ detalhes() |
<<interface>> Publicacao |
---|
+ abrir() + fechar() + folhear(p) + avancarPag() + voltarPag() |
Crie os arquivos de classes Pessoa.php, Livro.php e o de interface Publicacao.php.
Esse é o código da interface Publicacao:
interface Publicacao {
public function detalhes();
public function abrir();
public function fechar();
public function folhear($p);
public function avancarPag();
public function voltarPag();
}
Esse é o código da classe Pessoa:
class Pessoa {
private $nome;
private $idade;
private $sexo;
public function fazerAniver() {
$this->idade++;
}
public function __construct($nome, $idade, $sexo) {
$this->nome = $nome;
$this->idade = $idade;
$this->sexo = $sexo;
}
public function __destruct() {
echo "Objeto Pessoa Destruído!<br/>";
}
public function getNome() {
return $this->nome;
}
public function getIdade() {
return $this->idade;
}
public function getSexo() {
return $this->sexo;
}
public function setNome($nome) {
$this->nome = $nome;
}
public function setIdade($idade) {
$this->idade = $idade;
}
public function setSexo($sexo) {
$this->sexo = $sexo;
}
}
E esse é o código da classe Livro:
require_once "Pessoa.php";
require_once "Publicacao.php";
class Livro implements Publicacao {
private $titulo;
private $autor;
private $totPaginas;
private $pagAtual;
private $aberto;
private $leitor;
public function detalhes() {
echo "Livro " . $this->titulo . " escrito por " . $this->autor . ".";
if($this->aberto == true) {
echo "<br/>O livro está aberto!";
echo "<br/>Páginas: " . $this->totPaginas . ", página atual " . $this->pagAtual . ".";
echo "<br/>Sendo lido por " . $this->leitor->getNome() . ".";
echo "<br/>De idade de " . $this->leitor->getIdade() . " anos.";
echo "<br/>E de sexo " . $this->leitor->getSexo() . ".";
}
else {
echo "<br/>O livro está fechado no momento!";
}
}
public function abrir() {
$this->aberto = true;
}
public function avancarPag() {
if($this->getAberto() == true) {
if($this->getPagAtual() < $this->getTotPaginas()) {
$this->setPagAtual($this->getPagAtual() + 1);
}
}
}
public function fechar() {
$this->aberto = false;
}
public function folhear($p) {
if($this->getAberto() == true) {
if($p > $this->totPaginas) {
$this->setPagAtual($this->getTotPaginas());
}
else if($p < 0) {
$this->setPagAtual(0);
}
else {
$this->pagAtual = $p;
}
}
}
public function voltarPag() {
if($this->getAberto() == true) {
if($this->getPagAtual() > 0) {
$this->setPagAtual($this->getPagAtual() - 1);
}
}
}
public function __construct($titulo, $autor, $totPaginas, $leitor) {
$this->titulo = $titulo;
$this->autor = $autor;
$this->totPaginas = $totPaginas;
$this->leitor = $leitor;
$this->aberto = false;
$this->pagAtual = 0;
}
public function __destruct() {
unset($this->leitor); // Destruindo objeto no destrutor
echo "Objeto Livro Destruído!<br/>";
}
public function getTitulo() {
return $this->titulo;
}
public function getAutor() {
return $this->autor;
}
public function getTotPaginas() {
return $this->totPaginas;
}
public function getPagAtual() {
return $this->pagAtual;
}
public function getAberto() {
return $this->aberto;
}
public function getLeitor() {
return $this->leitor;
}
public function setTitulo($titulo) {
$this->titulo = $titulo;
}
public function setAutor($autor) {
$this->autor = $autor;
}
public function setTotPaginas($totPaginas) {
$this->totPaginas = $totPaginas;
}
public function setPagAtual($pagAtual) {
$this->pagAtual = $pagAtual;
}
public function setAberto($aberto) {
$this->aberto = $aberto;
}
public function setLeitor($leitor) {
$this->leitor = $leitor;
}
}
E no index, coloque isso:
require_once "Livro.php"; // Não é necessário carregar também Pessoa.php.
$p[0] = new Pessoa("Sérgio", 22, "M");
$p[1] = new Pessoa("Maria", 31, "F");
$l[0] = new Livro("PHP Básico", "José da Silva", 300, $p[0]);
$l[1] = new Livro("POO com PHP", "Maria de Souza", 500, $p[0]);
$l[2] = new Livro("PHP Avançado", "Ana Paula", 800, $p[1]);
$l[2]->abrir();
$l[2]->folhear(305); // Aqui se passa parâmetros;
$l[2]->avancarPag();
$l[2]->detalhes();
unset($p);
unset($l);
Teste outros "livros", outras funções.
PS: Tente colocar como privados os getters e setters.
Como sabemos, a POO tem três pilares, Encapsulamento, Herança e Polimorfismo (representados pelas letras EHP). O segundo que vamos tratar é a herança.
O conceito herança é o de mãe e filha, se definimos uma classe como mãe, todas as classes filhas herdam suas características e comportamentos.
A herança permite basear uma nova classe na definição de uma outra classe previamente existente. A classe filha é criada baseada na classe mãe já existente.
Lembra do objeto Caneta? Vamos supor uma caneta esferográfica comum, e queiramos fazer uma caneta com luzinha, vamos pegar a caneta já pronta (classe mãe), e colocaremos a luzinha nela (classe filha), mantendo as características e comportamentos da caneta (de escrever, ter tinta, etc.), para isso usamos uma caneta já pronta e adicionamos esses recursos.
Vamos supor que temos três pessoas, um aluno, um professor e um funcionário. Alguns atributos e métodos em comum entre eles colocaremos numa classe separada, que será a superclasse (progenitora ou mãe), e o Aluno, Professor e Funcionario serão subclasses (filhas). Veja o diagrama delas abaixo:
Pessoa |
---|
- nome - idade - sexo |
+ fazerAniver() |
Classes filhas:
Aluno |
---|
- matr - curso |
+cancelarMatr() |
Professor |
---|
- especialidade - salario |
+ receberAumento(aum) |
Funcionario |
---|
- setor - trabalhando |
+ mudarTrabalho() |
Vamos usar a classe Pessoa que criamos na aula anterior para isso. Mas elimine o método construtor dela.
Para ele "herdar" elementos de outra classe, usamos o extends
(extender), como veremos abaixo, na criação do arquivo Aluno.php com a classe Aluno:
require_once "Pessoa.php";
class Aluno extends Pessoa {
private $matr;
private $curso;
public function cancelarMatr() {
echo "<p>Matrícula será cancelada!</p>";
}
public function getMatr() {
return $this->matr;
}
public function getCurso() {
return $this->curso;
}
public function setMatr($matr) {
$this->matr = $matr;
}
public function setCurso($curso) {
$this->curso = $curso;
}
}
E fazer o mesmo com Professor.php:
require_once "Pessoa.php";
class Professor extends Pessoa {
private $especialidade;
private $salario;
public function receberAumento($aum) {
$this->salario += $aum;
}
public function getEspecialidade() {
return $this->especialidade;
}
public function getSalario() {
return $this->salario;
}
public function setEspecialidade($especialidade) {
$this->especialidade = $especialidade;
}
public function setSalario($salario) {
$this->salario = $salario;
}
}
E com funcionário:
require_once "Pessoa.php";
class Funcionario extends Pessoa {
private $setor;
private $trabalhando;
public function mudarTrabalho() {
$this->trabalhando = !$this->trabalhando;
}
public function getSetor() {
return $this->setor;
}
public function getTrabalhando() {
return $this->trabalhando;
}
public function setSetor($setor) {
$this->setor = $setor;
}
public function setTrabalhando($trabalhando) {
$this->trabalhando = $trabalhando;
}
}
E esse é o código do index:
require_once "Aluno.php";
require_once "Professor.php";
require_once "Funcionario.php";
$p1 = new Pessoa();
$p2 = new Aluno();
$p3 = new Professor();
$p4 = new Funcionario();
$p1->setNome("Sérgio");
$p2->setNome("Maria");
$p3->setNome("Cláudio");
$p4->setNome("Fabiana");
$p1->setSexo("M");
$p4->setSexo("F");
$p2->setCurso("Informática");
$p3->setSalario(2500.75);
$p4->setSetor("Estoque");
// Esses métodos não funcionarão, apenas nos objetos especificados, altere os objetos associados:
$p1->receberAumento(550.20);
$p2->mudarTrabalho();
$p4->cancelarMatr();
print_r($p1);
print_r($p2);
print_r($p3);
print_r($p4);
Aí podemos entender o que é herança, onde podemos criar objetos com alguns atributos padrão (no caso, Pessoa), e outros com especialidades.
No index, tente colocar outros "setter" pra todos os atributos.
PS: Não é possível uma mesma classe ter herança de mais de uma classe (herança múltipla), o que pode é uma classe ter uma herança e uma ou mais implementações de interfaces, seria algo tipo class NomeDaClasse2 extends NomeDaClasse1 implements NomeDaInterface
, a indicação da classe sempre vem antes das interfaces. E é possível usar o extends em interfaces, no caso de uma interface herdar os métodos de outras (em interfaces podemos ter herança de mais de uma interface).