Recentemente, encontrei dificuldades no processo de aprendizagem da interface PHP5. O livro dizia que é uma forma de implementar herança múltipla, mas ainda não sei como implementá-la. Há muito pouca informação sobre a interface PHP na Internet, então verifiquei em Java. Na verdade, eles são basicamente iguais. Depois de ler o artigo "Esclarecendo Java (Interfaces e Herança)", de repente percebi que o havia entendido mal desde o início. A chamada herança múltipla refere-se a interfaces que herdam classes, não a classes que herdam interfaces.
O artigo mencionava a abstração de OO Assim como a frase do artigo - “Abstração é remover a parte da imagem”, é muito vívido. Quando pensei em abstração, sempre achei difícil entender. , é fácil de entender agora. Sim, é exatamente isso que as interfaces e as classes abstratas fazem.
Há muitos outros pontos de vista no artigo que me beneficiaram muito, conforme listado abaixo:
A essência do OO, creio eu, é a abstração de objetos.
A função da interface, em poucas palavras, é marcar o tipo de classe. Atribuir diferentes tipos de classes a diferentes interfaces pode gerenciá-las melhor.
O objetivo da herança também é a abstração, não a reutilização de código.
Depois de ler este artigo, agora entendo basicamente como aplicar interfaces, classes abstratas e herança.
O texto original é o seguinte:
Esclarecendo Java (Interfaces e Herança) Meu irmão, estudante do segundo ano de graduação na Faculdade de Ciência da Computação, discutiu Java comigo. Quando nos conhecemos, várias perguntas eram sobre interfaces. Qual é o uso de interfaces? Por que usar interfaces? Quando você deve usar interfaces? Fico feliz que eles não tenham me perguntado como conectar-se ao SQL Server usando Java ou como desenvolver aplicativos J2EE. Essas questões são letais e devem ser evitadas. Este ano, a Faculdade de Ciência da Computação tem um projeto de graduação em J2ME. Os alunos que escolheram esse tema ainda estudavam o pacote java.util.* com uma careta no final de maio, isso e isso... suspiro.
A maioria das pessoas acredita que o propósito das interfaces é substituir a herança múltipla. Como todos sabemos, Java não possui um mecanismo de herança múltipla como C++, mas pode implementar múltiplas interfaces. Na verdade, isso é absurdo. Interfaces e herança são coisas completamente diferentes. As interfaces não têm capacidade de substituir herança múltipla e não têm essa obrigação. A função da interface, em poucas palavras, é marcar o tipo de classe. Atribuir diferentes tipos de classes a diferentes interfaces pode gerenciá-las melhor. Acho que a essência do OO é a abstração de objetos, e a interface incorpora melhor isso. A razão pela qual discutimos padrões de design apenas para linguagens com capacidades abstratas (como c++, java, c#, etc.) é porque o que os padrões de design estudam é, na verdade, como abstrair razoavelmente. (O famoso ditado do Cowboy é “Abstração é remover a parte da imagem”, o que parece uma piada, mas na verdade é verdade).
O mais básico dos padrões de design é o padrão Factory. Em um aplicativo muito simples que fiz recentemente, eu queria tentar o meu melhor para tornar meu programa portátil entre vários bancos de dados. É claro que isso envolve muitos problemas, incluindo como fazer a compatibilidade do SQL. de diferentes DBMS é uma dor de cabeça. Poderíamos também simplificar o problema primeiro e considerar apenas como conectar diferentes bancos de dados.
Suponha que eu tenha muitas classes, nomeadamente Mysql.java, SQLServer.java, Oracle.java e DB2.java. Elas se conectam a bancos de dados diferentes respectivamente, retornam um objeto Connection uniformemente e todas possuem um método close para fechar a conexão. Você só precisa selecionar classes diferentes para o seu SGBD e poderá usá-lo. Mas qual banco de dados meu usuário usará? Não sei, o que espero é modificar o código o mínimo possível para atender às necessidades dele. Posso abstrair a seguinte interface:
pacoteorg.bromon.test;
banco de dados de interface pública
{
java.sql.Connection openDB (String url,String usuário,String senha);
void fechar();
}
Esta interface define apenas dois métodos sem nenhum código significativo. O código específico é fornecido pela classe que implementa esta interface, como Mysql.java:
Package org.bromon.test;
importar java.sql.*;
classe pública Mysql implementa banco de dados
{
private String url="jdbc:mysql:localhost:3306/test";
string privada usuário = "root";
senha de string privada=””;
conexão de conexão privada;
Conexão pública openDB (url, usuário, senha)
{
//Código para conectar ao banco de dados}
public void close()
{
//Fecha o banco de dados}
}
Outros semelhantes são, claro, Oracle.java, etc. A interface DB classifica essas classes. Na aplicação, definimos o objeto assim:
org.bromon.test.DB myDB
usa myDB para operar o banco de dados. Não preciso me preocupar com isso. A classe que estou usando é chamada de princípio "aberto-fechado". Mas o problema é que a interface não pode ser instanciada, myDB=new DB(), esse código está absolutamente errado, só podemos myDB=new Mysql() ou myDB=new Oracle(). Desculpe, ainda preciso especificar qual classe será instanciada. Usar uma interface é inútil. Então precisamos de uma fábrica:
package org.bromon.test;
classe pública DBFactory
{
Conexão de banco de dados estática pública getConn()
{
Return(novo Mysql());
}
}
Portanto, o código de instanciação se torna: myDB=DBFactory.getConn();
Esta é a fábrica comum mais básica (Factory) entre os 23 modos. A classe de fábrica é responsável por instanciar especificamente qual classe e outras lógicas de programa operam na interface do banco de dados. As responsabilidades foram passadas para a classe de fábrica. Claro, você também pode continuar a definir a interface de fábrica e aumentar as responsabilidades, o que evolui para uma fábrica abstrata.
A interface não é responsável por nenhuma operação específica durante todo o processo. Se outros programas quiserem se conectar ao banco de dados, eles só precisam construir um objeto de banco de dados, independentemente de como a classe de fábrica muda. É disso que tratam as interfaces - abstração.
Escusado será dizer que o conceito de herança é fácil de entender. Por que herdar? Porque você deseja reutilizar o código? Definitivamente, esse não é um motivo. O objetivo da herança é a abstração, não a reutilização de código. Se o objeto A tiver um método run(), o objeto B também deseja ter esse método, então alguém usa a Classe B estende A. Esta é uma abordagem estúpida. Se você instanciar A em B e chamar o método Run() de A, o mesmo propósito poderá ser alcançado? do seguinte modo:
Classe B
{
A = novo A();
a.run();
}
Trata-se de usar a agregação de classes para reutilizar código. É o protótipo do modelo de delegação e uma prática que GoF sempre defendeu.
Então, qual é o objetivo da herança? Na verdade, isso é causado por razões históricas. A linguagem OO original só tinha herança e não tinha interfaces, então a abstração só poderia ser alcançada por meio de herança. Observe que a intenção original da herança é a abstração, não a reutilização de código (embora a herança também tenha isso). efeito). Este é um dos erros mais graves de muitos livros ruins sobre Java. Não me livrei completamente da sombra que eles causaram. Quando você deve usar herança? Utilize-o apenas em classes abstratas, procure não utilizá-lo em outras situações. Classes abstratas não podem ser instanciadas. Elas apenas fornecem um modelo que ilustra o problema.
A raiz de todos os males no desenvolvimento de software, especialmente entre os programadores C++, é a duplicação de código em vez da reutilização de código e o uso indevido de herança. O objetivo de proibir a herança múltipla em Java é impedir o mau uso da herança. É uma abordagem muito sábia, mas muitas pessoas não a entendem. Java pode refletir melhor o design, e essa é uma das razões pelas quais estou fascinado.