Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Israel Elias

Interface POO

Recommended Posts

Tudo bem pessoa pessoal


Antes de tudo queria parabenizar o pessoal aqui do fórum iMasters, por sempre me ajudar e ter a paciência de explicar, estou aprendendo e muito com vocês =)


Separei algumas dúvidas que tenho sobre interface, aqui são elas veja:


1) Interface não e só para enfeite, sei que existe um motivo dela existir, qual o principal motivo de um programador criar uma interface??


2) Em que momento eu usaria interface??


3) Qual a diferença de interface para class abstract??


4) Sempre vejo uma galera falando sobre "interface dos objetos", eles estão falando da classe interface??


5) Quando estiver fazendo um sistema e eu começar a notar que vários objetos que tem comportamentos em comum(código duplicado), como saber se devo usar interface ou classe abstract para padronizar esses comportamentos em comum(código duplicado)??


Desde de já, obrigado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

O uso mais básico e corriqueiro é polimorfismo:

<?php

interface DataStorage {
  public function store($data);
  public function reead();
}

class FileDataStorage implements DataStorage {
  private $file;

  public function __construct($file) {
    $this->file = $file;
  }

  public function store($data) {
    file_put_contents($this->file, serialize($data));
  }

  public function read() {
    return unserialize(file_get_contents($this->file));
  }
}

class ApcDataStorage implements DataStorage {
  public function store($data) {
    apc_store('foobarbaz', $data);
  }

  public function read() {
    return apc_fetch('foobarbaz');
  }
}

class Application {
  private $storage;

  public function __construct(DataStorage $storage) {
    $this->storage = $storage;
  }

  // ...
}

// Podemos rodar a aplicação usando arquivo
$app = new Application(new FileDataStorage('foo.txt'));
// Ou também podemos usar APC, ou
// qualquer outro data storage que
// implemente a interface DataStorage,
// diminuindo o acoplamento e dando flexibilidade
$app = new Application(new ApcDataStorage());

 

1 - Criar um contrato para que o código possa confiar num contrato ao invés de criar um acoplamento com uma implementação específica.

2 - Sempre que você deseja abstrair algo.

3 - Uma interface é um contrato, sem comportamento. Uma classe abstrata é uma classe base com comportamentos.

4 - Não necessariamente. Geralmente eles estão falando sobre a API pública das classes.

5 - Interfaces = contratos. Classes abstratas são classes bases para reduzir duplicação.

Compartilhar este post


Link para o post
Compartilhar em outros sites

É incrível como em POO a gente sempre descobre coisas novas ao longo dos estudo.

 

5 - Interfaces = contratos. Classes abstratas são classes bases para reduzir duplicação.

- Qual real significado de contrato em POO??
- Tem diferença entre reduzir duplicação no caso a "classe abstrata" e fazer contrato no caso "interface"??

1 - Criar um contrato para que o código possa confiar num contrato ao invés de criar um acoplamento com uma implementação específica.

Acoplamento?? O seria em POO??

Compartilhar este post


Link para o post
Compartilhar em outros sites

- Qual real significado de contrato em POO??

 

Ele diz que você é obrigado a usar os métodos definidos na interface.

 

falando a grosso modo na interface você vai criar métodos vazios onde vc terá comportamentos conceituais.

 

 

Interface animal {

function emitir_som(){

 

}

}

veja que eu não defini qual o som do animal mas todo todos os objetos que estenderem essa interface vão precisa emitir um som obrigatoriamente mas cada animal tem faz um barulho diferente então no objeto você define qual som.

 

 

Class gato extends animal {
  public function emitir_som(){
    echo 'miaaau';
  }
}


Class lobo extends animal {
  public function emitir_som(){
    echo 'auuuuuuuuuuuuuuuuuuuuuuuuuuu';
  }
}

enquanto objetos abstratos já vai te dar comportamento para esses objetos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Israel Elias, dá uma lida:

 

http://wbruno.com.br/php/afinal-e-interface-oop/

Compartilhar este post


Link para o post
Compartilhar em outros sites

Qual a diferença entre classes abstrata e interface na prática?? Vocês poderiam me dá um exemplo claro, da diferença entre as duas??

Compartilhar este post


Link para o post
Compartilhar em outros sites

Uma interface é um contrato, sem comportamento definido. Ela define apenas uma API que uma classe que desejar implementá-la terá de seguir.

 

Vamos considerar a seguinte classe de banco de dados:

class Database
{
    private $pdo;
    private $databaseType;

    public function __construct($databaseType, $name, $host, $user, $password)
    {
        if ($databaseType === 'mysql') {
            $this->pdo = new PDO("mysql:host={$host};dbname={$name}", $user, $password);
        } elseif ($databaseType === 'postgre') {
            $this->pdo = new PDO("pgsql:host={$host};dbname={$name}", $user, $password);
        } else {
            throw new InvalidArgumentException('Database not supported.');
        }

        $this->databaseType = $databaseType;
    }

    public function insert($table, array $data)
    {
        $query = sprintf(
            'INSERT INTO %s (%s) VALUES (%s)',
            $table,
            implode(', ', array_keys($data)),
            implode(', ', array_values($data))
        );

        $statement = $this->pdo->prepare($query);
        $statement->execute();
    }

    public function isDatabase($database)
    {
        if ($database === 'MySQL' && $database === 'mysql') {
            return true;
        } elseif ($database === 'PostgreSQL' && $database === 'postgre') {
            return true;
        } else {
            return false;
        }
    }
}

 

E podemos usá-la assim:

 

// Com MySQL
$database = new Database('mysql', 'my_app', 'localhost', 'johndoe', '12345');
$database->insert('users', ['name' => 'John Doe']); // Insere um usuário no mysql
$database->isDatabase('MySQL'); // true
$database->isDatabase('PostgreSQL'); // false
$database->isDatabase('Oracle'); // false

// Com PostgreSQL
$database = new Database('postgre', 'my_app', 'localhost', 'johndoe', '12345');
$database->insert('users', ['name' => 'John Doe']); // Insere um usuário no postgre
$database->isDatabase('MySQL'); // false
$database->isDatabase('PostgreSQL'); // true
$database->isDatabase('Oracle'); // false

O código é funcional e atende às nossas necessidades, mas ele tem um problema grande: se quisermos adicionar suporte para mais um banco de dados (SQLite, MariaDB, etc.), precisaríamos editar a classe Database, colocando mais um if lá. Isto viola um princípio de design importante, o Open/Closed Principle.

 

Para resolver este problema, na verdade, não é muito difícil. Se pararmos para pensar, basta criarmos classes para representarem tipos de bancos de dados e passar uma instância dela para a classe Database. Veja:

class MySQL
{
    private $pdo;

    public function __construct($name, $host, $user, $password)
    {
        $this->pdo = new PDO("mysql:host={$host};dbname={$name}", $user, $password);
    }

    public function executeQuery($query)
    {
        $statement = $this->pdo->prepare($query);
        $statement->execute();
    }

    public function getDatabaseName()
    {
        return 'MySQL';
    }
}

class PostgreSQL
{
    private $pdo;

    public function __construct($name, $host, $user, $password)
    {
        $this->pdo = new PDO("pgsql:host={$host};dbname={$name}", $user, $password);
    }

    public function executeQuery($query)
    {
        $statement = $this->pdo->prepare($query);
        $statement->execute();
    }

    public function getDatabaseName()
    {
        return 'PostgreSQL';
    }
}

class Database
{
    private $connection;

    public function __construct($connection)
    {
        $this->connection = $connection;
    }

    public function insert($table, array $data)
    {
        $query = sprintf(
            'INSERT INTO %s (%s) VALUES (%s)',
            $table,
            implode(', ', array_keys($data)),
            implode(', ', array_values($data))
        );

        $this->connection->executeQuery($query);
    }

    public function isDatabase($database)
    {
        return $database === $this->connection->getDatabaseName();
    }
}

E agora para usar:

$database = new Database(new MySQL('mysql', 'my_app', 'localhost', 'johndoe', '12345'));
$database->insert('users', ['name' => 'John Doe']); // Insere um usuário no mysql
$database->isDatabase('MySQL'); // true
$database->isDatabase('PostgreSQL'); // false
$database->isDatabase('Oracle'); // false

$database = new Database(new PostgreSQL('postgre', 'my_app', 'localhost', 'johndoe', '12345'));
$database->insert('users', ['name' => 'John Doe']); // Insere um usuário no postgre
$database->isDatabase('MySQL'); // false
$database->isDatabase('PostgreSQL'); // true
$database->isDatabase('Oracle'); // false

Agora, se desejarmos criar um novo tipo de conexão, basta criarmos uma classe para esse banco de dados e passar para nossa classe. Flexibilidade alcançada :graduated:.

 

Esse tipo de abordagem é chamada de duck-typing, que basicamente é se preocupar com o comportamento, e não com o tipo, criando um contrato implícito (você em momento nenhum disse o que um conector de banco de dados deve ter).

 

Todavia, o PHP tem suporte à interfaces, que são uma forma de fazer contratos explícitos (você define o que um conector de um banco de dados deve ter). O mesmo código acima usando interfaces:

 

interface DatabaseConnection
{
    public function executeQuery($query);
    public function getDatabaseName();
}

class MySQL implements DatabaseConnection
{
    private $pdo;

    public function __construct($name, $host, $user, $password)
    {
        $this->pdo = new PDO("mysql:host={$host};dbname={$name}", $user, $password);
    }

    public function executeQuery($query)
    {
        $statement = $this->pdo->prepare($query);
        $statement->execute();
    }

    public function getDatabaseName()
    {
        return 'MySQL';
    }
}

class PostgreSQL implements DatabaseConnection
{
    private $pdo;

    public function __construct($name, $host, $user, $password)
    {
        $this->pdo = new PDO("pgsql:host={$host};dbname={$name}", $user, $password);
    }

    public function executeQuery($query)
    {
        $statement = $this->pdo->prepare($query);
        $statement->execute();
    }

    public function getDatabaseName()
    {
        return 'PostgreSQL';
    }
}

class Database
{
    private $connection;

    public function __construct(DatabaseConnection $connection)
    {
        $this->connection = $connection;
    }

    public function insert($table, array $data)
    {
        $query = sprintf(
            'INSERT INTO %s (%s) VALUES (%s)',
            $table,
            implode(', ', array_keys($data)),
            implode(', ', array_values($data))
        );

        $this->connection->executeQuery($query);
    }

    public function isDatabase($database)
    {
        return $database === $this->connection->getDatabaseName();
    }
}

 

Agora, há uma interface DatabaseConnection que define uma API pública comum a todos os conectores de banco de dados. A partir disso, os conectores implementam essa interface, o que os obriga a implementar os métodos que a interface declara. Por fim, usamos type hinting na classe Database para garantir que o conector passado implementa a interface DatabaseConnection.

 

Bem, não há melhor ou pior (entre duck-typing e interfaces). Algumas linguagens requisitam de você a tipagem (Java), outras não permitem nativamente (Ruby, Python) e outras te dão a liberdade de escolher (PHP, Scala).

 

---

 

 

Uma classe abstrata está relacionada com comportamento comum de classes. Ela é uma classe base que não pode ser instanciada e serve para reduzir duplicação de código. Elas não têm o mesmo propósito das interfaces e elas não substituem as interfaces.

 

Para o post não ficar enorme, eu já dei um exemplo simples num tópico aqui do fórum: http://forum.imasters.com.br/topic/508589-classes-abstract/?p=2012223

 

Espero que tenha ajudado =)

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.