Récemment, j'ai rencontré des difficultés dans le processus d'apprentissage de l'interface PHP5. Le livre disait que c'était un moyen d'implémenter l'héritage multiple, mais je ne sais toujours pas comment l'implémenter. Il y a très peu d'informations sur l'interface PHP sur Internet, j'ai donc vérifié sur Java. En fait, elles sont fondamentalement les mêmes. Après avoir lu l'article "Clarifier Java (interfaces et héritage)", j'ai soudain réalisé que je l'avais mal compris depuis le début. Le soi-disant héritage multiple fait référence aux interfaces héritant de classes, et non aux classes héritant d'interfaces.
L'article mentionnait l'abstraction de OO. Tout comme la phrase de l'article - "L'abstraction consiste à supprimer la partie image", c'est très vivant. Quand je pensais à l'abstraction, j'ai toujours pensé que c'était difficile à comprendre. , c'est facile à comprendre maintenant. Oui, c'est exactement ce que font les interfaces et les classes abstraites.
Il y a de nombreux autres points de vue dans l’article qui m’ont beaucoup profité, comme indiqué ci-dessous :
L’essence de l’OO, je pense, est l’abstraction des objets.
En résumé, la fonction de l’interface est de marquer le type de classe. Attribuer différents types de classes à différentes interfaces permet de mieux les gérer.
Le point de l’héritage est également l’abstraction, pas la réutilisation du code.
Après avoir lu cet article, je comprends maintenant comment appliquer les interfaces, les classes abstraites et l'héritage.
Le texte original est le suivant :
Clarifier Java (interfaces et héritage) Mon frère, étudiant de deuxième année à l'École d'informatique, a discuté de Java avec moi lorsque nous nous sommes rencontrés, plusieurs questions concernaient toutes les interfaces. Pourquoi utiliser des interfaces ? Quand faut-il utiliser les interfaces ? Je suis heureux qu'ils ne m'aient pas demandé comment me connecter à SQL Server à l'aide de Java ou comment développer des applications J2EE. De telles questions sont mortelles et doivent être évitées. Cette année, l'École d'informatique a un projet de fin d'études sur J2ME. Les étudiants qui ont choisi ce sujet étudiaient encore le package java.util.* avec une grimace fin mai, ceci et cela... soupir.
La plupart des gens pensent que le but des interfaces est de remplacer l’héritage multiple. Comme nous le savons tous, Java ne dispose pas d’un mécanisme d’héritage multiple comme C++, mais il peut implémenter plusieurs interfaces. En fait, c'est tiré par les cheveux. Les interfaces et l'héritage sont des choses complètement différentes. Les interfaces n'ont pas la capacité de remplacer l'héritage multiple, et elles n'ont pas une telle obligation. En résumé, la fonction de l’interface est de marquer le type de classe. Attribuer différents types de classes à différentes interfaces permet de mieux les gérer. Je pense que l’essence de OO est l’abstraction des objets, et l’interface l’incarne le mieux. La raison pour laquelle nous discutons des modèles de conception uniquement pour les langages dotés de capacités abstraites (tels que C++, Java, C#, etc.) est due au fait que ce que les modèles de conception étudient est en fait la manière d'abstraire raisonnablement. (Le célèbre dicton de Cowboy est "L'abstraction consiste à supprimer la partie de l'image", ce qui semble être une blague, mais est en réalité vrai).
Le modèle de conception le plus basique est le modèle Factory. Dans une application très simple que j'ai récemment créée, je voulais faire de mon mieux pour rendre mon programme portable entre plusieurs bases de données. Bien sûr, cela implique de nombreux problèmes, notamment la compatibilité de SQL. à partir de différents SGBD est un casse-tête. Autant simplifier le problème d’abord et considérer uniquement comment connecter différentes bases de données.
Supposons que j'ai plusieurs classes, à savoir Mysql.java, SQLServer.java, Oracle.java et DB2.java. Elles se connectent respectivement à différentes bases de données, renvoient un objet Connection de manière uniforme et disposent toutes d'une méthode close pour fermer la connexion. Il vous suffit de sélectionner différentes classes pour votre SGBD et vous pouvez l'utiliser. Mais quelle base de données mon utilisateur utilisera-t-il ? Je ne sais pas, ce que j'espère c'est modifier le code le moins possible pour répondre à ses besoins. Je peux résumer l'interface suivante :
paquet org.bromon.test ;
Base de données d'interface publique
{
java.sql.Connection openDB (URL de chaîne, utilisateur de chaîne, mot de passe de chaîne);
annuler fermer();
}
Cette interface ne définit que deux méthodes sans aucun code significatif. Le code spécifique est donné par la classe qui implémente cette interface, comme Mysql.java :
Package org.bromon.test;
importer java.sql.* ;
classe publique Mysql implémente DB
{
private String url="jdbc:mysql:localhost:3306/test";
chaîne privée user="root";
mot de passe de chaîne privée = "" ;
connexion de connexion privée ;
Connexion publique openDB (url, utilisateur, mot de passe)
{
//Code pour se connecter à la base de données}
public void close()
{
//Fermer la base de données}
}
Les similaires sont bien sûr Oracle.java, etc. L'interface DB classe ces classes dans l'application, nous définissons l'objet comme ceci :
org.bromon.test.DB myDB
utilise myDB pour faire fonctionner la base de données, et vous ne le faites pas. Je n'ai pas à m'en soucier. La classe que j'utilise réellement est ce qu'on appelle le principe "ouvert-fermé". Mais le problème est que l'interface ne peut pas être instanciée, myDB=new DB(), un tel code est absolument faux, nous ne pouvons que myDB=new Mysql() ou myDB=new Oracle(). Désolé, je dois encore préciser quelle classe doit être instanciée. Utiliser une interface est inutile. Nous avons donc besoin d'une usine :
package org.bromon.test ;
classe publique DBFactory
{
Connexion à la base de données statique publique getConn()
{
Retour(nouveau Mysql());
}
}
Le code d'instanciation devient donc : myDB=DBFactory.getConn();
Il s'agit de l'usine ordinaire (Factory) la plus basique parmi les 23 modes. La classe d'usine est chargée d'instancier spécifiquement la classe et les autres logiques de programme qui fonctionnent sur l'interface DB. Les responsabilités ont été transférées à la classe d'usine. Bien entendu, vous pouvez également continuer à définir l'interface d'usine et continuer à assumer les responsabilités, ce qui évolue vers une usine abstraite.
L'interface n'est responsable d'aucune opération spécifique pendant tout le processus. Si d'autres programmes souhaitent se connecter à la base de données, il leur suffit de construire un objet DB, quelle que soit la façon dont la classe d'usine change. C’est à cela que servent les interfaces : l’abstraction.
Il va sans dire que la notion d’héritage est facile à comprendre. Pourquoi hériter ? Parce que vous voulez réutiliser du code ? Ce n’est certainement pas une raison. Le but de l’héritage est l’abstraction, pas la réutilisation du code. Si l'objet A a une méthode run(), l'objet B veut également avoir cette méthode, donc quelqu'un utilise la classe B étend A. Il s’agit d’une approche insensée. Si vous instanciez A dans B et appelez la méthode Run() de A, le même objectif peut-il être atteint ? comme suit:
Classe B
{
A a=nouveau A();
a.run();
}
Il s'agit d'utiliser l'agrégation de classes pour réutiliser du code. C'est le prototype du modèle de délégation et une pratique que GoF a toujours préconisée.
Alors à quoi sert l’héritage ? En fait, cela est dû à des raisons historiques. Le langage OO d'origine n'avait qu'un héritage et aucune interface, donc l'abstraction ne pouvait être réalisée que par l'héritage. Veuillez noter que l'intention initiale de l'héritage est l'abstraction, pas la réutilisation du code (bien que l'héritage ait également cela). effet). C'est l'une des erreurs les plus graves de nombreux mauvais livres Java. Je ne me suis pas complètement débarrassé de l'ombre qu'ils ont causée. Les mauvais livres sont nocifs, en particulier les livres d'introduction. Quand faut-il recourir à l’héritage ? Utilisez-le uniquement dans des classes abstraites, essayez de ne pas l'utiliser dans d'autres situations. Les classes abstraites ne peuvent pas être instanciées. Elles fournissent uniquement un modèle qui illustre le problème.
La racine de tous les maux dans le développement de logiciels, en particulier chez les programmeurs C++, réside dans la duplication du code au lieu de sa réutilisation et dans l’utilisation abusive de l’héritage. Le but de l'interdiction de l'héritage multiple en Java est de mettre fin à la mauvaise utilisation de l'héritage. C'est une approche très judicieuse, mais beaucoup de gens ne la comprennent pas. Java peut mieux refléter le design, ce qui est l'une des raisons pour lesquelles je suis fasciné.