JavaRush /Blog Java /Random-FR /Conception de classes et d'interfaces (Traduction de l'ar...
fatesha
Niveau 22

Conception de classes et d'interfaces (Traduction de l'article)

Publié dans le groupe Random-FR
Conception de classes et d'interfaces (Traduction de l'article) - 1

Contenu

  1. Introduction
  2. Interfaces
  3. Marqueurs d'interface
  4. Interfaces fonctionnelles, méthodes statiques et méthodes par défaut
  5. Cours abstraits
  6. Classes immuables (permanentes)
  7. Cours anonymes
  8. Visibilité
  9. Héritage
  10. Héritage multiple
  11. Héritage et composition
  12. Encapsulation
  13. Cours finaux et méthodes
  14. Et après
  15. Télécharger le code source

1. INTRODUCTION

Quel que soit le langage de programmation que vous utilisez (et Java ne fait pas exception), suivre de bons principes de conception est la clé pour écrire un code propre, compréhensible et vérifiable ; et également le créer pour qu'il soit durable et facilite la résolution de problèmes. Dans cette partie du didacticiel, nous allons aborder les éléments de base fournis par le langage Java et présenter quelques principes de conception dans le but de vous aider à prendre de meilleures décisions de conception. Plus précisément, nous allons aborder les interfaces et les interfaces utilisant les méthodes par défaut (une nouveauté de Java 8), les classes abstraites et finales, les classes immuables, l'héritage, la composition, et revoir les règles de visibilité (ou d'accessibilité) que nous avons brièvement évoquées dans Leçon de la première partie "Comment créer et détruire des objets" .

2. INTERFACES

En programmation orientée objet , le concept d'interfaces constitue la base du développement des contrats . En un mot, les interfaces définissent un ensemble de méthodes (contrats) et chaque classe qui nécessite la prise en charge de cette interface spécifique doit fournir une implémentation de ces méthodes : une idée assez simple mais puissante. De nombreux langages de programmation ont des interfaces sous une forme ou une autre, mais Java en particulier fournit un support linguistique pour cela. Jetons un coup d'œil à une définition d'interface simple en Java.
package com.javacodegeeks.advanced.design;

public interface SimpleInterface {
void performAction();
}
Dans l'extrait ci-dessus, l'interface que nous avons appelée SimpleInterfacedéclare une seule méthode appelée performAction. La principale différence entre les interfaces et les classes est que les interfaces décrivent ce que devrait être le contact (elles déclarent une méthode), mais ne fournissent pas leur implémentation. Cependant, les interfaces en Java peuvent être plus complexes : elles peuvent inclure des interfaces imbriquées, des classes, des décomptes, des annotations et des constantes. Par exemple:
package com.javacodegeeks.advanced.design;

public interface InterfaceWithDefinitions {
    String CONSTANT = "CONSTANT";

    enum InnerEnum {
        E1, E2;
    }

    class InnerClass {
    }

    interface InnerInterface {
        void performInnerAction();
    }

    void performAction();
}
Dans cet exemple plus complexe, les interfaces imposent de manière inconditionnelle plusieurs restrictions aux constructions d'imbrication et aux déclarations de méthodes, et celles-ci sont appliquées par le compilateur Java. Tout d’abord, même si elle n’est pas explicitement déclarée, chaque déclaration de méthode dans une interface est publique (et ne peut être que publique). Ainsi les déclarations de méthode suivantes sont équivalentes :
public void performAction();
void performAction();
Il convient de mentionner que chaque méthode d'une interface est implicitement déclarée abstract , et même ces déclarations de méthode sont équivalentes :
public abstract void performAction();
public void performAction();
void performAction();
Quant aux champs constants déclarés, en plus d'être public , ils sont aussi implicitement static et marqués final . Les déclarations suivantes sont donc également équivalentes :
String CONSTANT = "CONSTANT";
public static final String CONSTANT = "CONSTANT";
Enfin, les classes, interfaces ou comptes imbriqués, en plus d'être public , sont également implicitement déclarés static . Par exemple, ces déclarations sont également équivalentes à :
class InnerClass {
}

static class InnerClass {
}
Le style que vous choisissez est une préférence personnelle, mais connaître ces propriétés simples des interfaces peut vous éviter une saisie inutile.

3. Marqueur d'interface

Une interface de marqueur est un type spécial d'interface qui ne possède pas de méthodes ou d'autres constructions imbriquées. Comment la bibliothèque Java le définit :
public interface Cloneable {
}
Les marqueurs d'interface ne sont pas des contrats en soi, mais constituent une technique quelque peu utile pour « attacher » ou « associer » un trait spécifique à une classe. Par exemple, en ce qui concerne Cloneable , la classe est marquée comme clonable, mais la manière dont cela peut ou doit être implémenté ne fait pas partie de l'interface. Un autre exemple très connu et largement utilisé de marqueur d’interface estSerializable :
public interface Serializable {
}
Cette interface marque la classe comme étant adaptée à la sérialisation et à la désérialisation, et encore une fois, elle ne précise pas comment cela peut ou doit être implémenté. Les marqueurs d'interface ont leur place dans la programmation orientée objet, bien qu'ils ne répondent pas à l'objectif principal d'une interface qui est d'être un contrat. 

4. INTERFACES FONCTIONNELLES, MÉTHODES PAR DÉFAUT ET MÉTHODES STATIQUES

Depuis les sorties de Java 8, les interfaces ont acquis de nouvelles fonctionnalités très intéressantes : méthodes statiques, méthodes par défaut et conversion automatique depuis les lambdas (interfaces fonctionnelles). Dans la section interfaces, nous avons souligné le fait que les interfaces en Java peuvent uniquement déclarer des méthodes, mais ne fournissent pas leur implémentation. Avec une méthode par défaut, les choses sont différentes : une interface peut marquer une méthode avec le mot-clé default et lui fournir une implémentation. Par exemple:
package com.javacodegeeks.advanced.design;

public interface InterfaceWithDefaultMethods {
    void performAction();

    default void performDefaulAction() {
        // Implementation here
    }
}
Au niveau de l'instance, les méthodes par défaut pourraient être remplacées par chaque implémentation d'interface, mais les interfaces peuvent désormais également inclure des méthodes statiques , par exemple : package com.javacodegeeks.advanced.design ;
public interface InterfaceWithDefaultMethods {
    static void createAction() {
        // Implementation here
    }
}
On pourrait dire que fournir l’implémentation dans l’interface va à l’encontre de l’objectif même de la programmation contractuelle. Mais il existe de nombreuses raisons pour lesquelles ces fonctionnalités ont été introduites dans le langage Java et peu importe leur utilité ou leur confusion, elles sont là pour vous et votre usage. Les interfaces fonctionnelles sont une autre histoire et se sont révélées être des ajouts très utiles au langage. Fondamentalement, une interface fonctionnelle est une interface sur laquelle une seule méthode abstraite est déclarée. RunnableL'interface de bibliothèque standard est un très bon exemple de ce concept.
@FunctionalInterface
public interface Runnable {
    void run();
}
Le compilateur Java traite les interfaces fonctionnelles différemment et peut transformer une fonction lambda en une implémentation d'interface fonctionnelle là où cela a du sens. Considérons la description de fonction suivante : 
public void runMe( final Runnable r ) {
    r.run();
}
Pour appeler cette fonction en Java 7 et versions antérieures, une implémentation de l'interface doit être fournie Runnable(par exemple en utilisant des classes anonymes), mais en Java 8 il suffit de fournir une implémentation de la méthode run() en utilisant la syntaxe lambda :
runMe( () -> System.out.println( "Run!" ) );
De plus, l' annotation @FunctionalInterface (les annotations seront traitées en détail dans la partie 5 du didacticiel) laisse entendre que le compilateur peut vérifier si une interface ne contient qu'une seule méthode abstraite, de sorte que toute modification apportée à l'interface à l'avenir ne violera pas cette hypothèse. .

5. COURS ABSTRAITS

Un autre concept intéressant supporté par le langage Java est le concept de classes abstraites. Les classes abstraites sont quelque peu similaires aux interfaces de Java 7 et sont très proches de l'interface de méthode par défaut de Java 8. Contrairement aux classes classiques, une classe abstraite ne peut pas être instanciée, mais elle peut être sous-classée (reportez-vous à la section Héritage pour plus de détails). Plus important encore, les classes abstraites peuvent contenir des méthodes abstraites : un type particulier de méthode sans implémentation, tout comme une interface. Par exemple:
package com.javacodegeeks.advanced.design;

public abstract class SimpleAbstractClass {
    public void performAction() {
        // Implementation here
    }

    public abstract void performAnotherAction();
}
Dans cet exemple, la classe SimpleAbstractClassest déclarée comme abstraite et contient une méthode abstraite déclarée. Les classes abstraites sont très utiles ; la plupart, voire certaines parties des détails d’implémentation peuvent être partagées entre de nombreuses sous-classes. Quoi qu'il en soit, ils laissent toujours la porte entrouverte et permettent de personnaliser le comportement inhérent à chacune des sous-classes à l'aide de méthodes abstraites. Il convient de mentionner que contrairement aux interfaces, qui ne peuvent contenir que des déclarations publiques , les classes abstraites peuvent utiliser toute la puissance des règles d'accessibilité pour contrôler la visibilité d'une méthode abstraite.

6. COURS IMMÉDIATS

De nos jours, l’immuabilité devient de plus en plus importante dans le développement de logiciels. L’essor des systèmes multicœurs a soulevé de nombreux problèmes liés au partage de données et au parallélisme. Mais un problème est définitivement apparu : avoir peu (voire pas) d’état mutable conduit à une meilleure extensibilité (évolutivité) et à un raisonnement plus facile sur le système. Malheureusement, le langage Java ne fournit pas de support décent pour l'immuabilité des classes. Cependant, en utilisant une combinaison de techniques, il devient possible de concevoir des classes immuables. Tout d'abord, tous les champs de la classe doivent être final (marqués comme final ). C'est un bon début, mais ce n'est pas une garantie. 
package com.javacodegeeks.advanced.design;

import java.util.Collection;

public class ImmutableClass {
    private final long id;
    private final String[] arrayOfStrings;
    private final Collection<String> collectionOfString;
}
Deuxièmement, assurez-vous d'une initialisation correcte : si un champ est une référence à une collection ou à un tableau, n'attribuez pas ces champs directement à partir des arguments du constructeur, faites plutôt des copies. Cela garantira que l’état de la collection ou du tableau n’est pas modifié en dehors de celui-ci.
public ImmutableClass( final long id, final String[] arrayOfStrings,
        final Collection<String> collectionOfString) {
    this.id = id;
    this.arrayOfStrings = Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
    this.collectionOfString = new ArrayList<>( collectionOfString );
}
Et enfin, assurer un accès approprié (getters). Pour les collections, l'immuabilité doit être fournie en tant que wrapper  Collections.unmodifiableXxx: avec les tableaux, la seule façon de fournir une véritable immuabilité est de fournir une copie au lieu de renvoyer une référence au tableau. Cela peut ne pas être acceptable d'un point de vue pratique, car cela dépend fortement de la taille du tableau et peut exercer une pression énorme sur le ramasse-miettes.
public String[] getArrayOfStrings() {
    return Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
}
Même ce petit exemple donne une bonne idée que l'immuabilité n'est pas encore un citoyen de premier ordre en Java. Les choses peuvent devenir compliquées si une classe immuable possède un champ qui fait référence à un objet d'une autre classe. Ces classes devraient également être immuables, mais il n’existe aucun moyen de le garantir. Il existe plusieurs analyseurs de code source Java décents, comme FindBugs et PMD, qui peuvent grandement vous aider en vérifiant votre code et en signalant les défauts courants de programmation Java. Ces outils sont de grands amis de tout développeur Java.

7. COURS ANONYMES

Avant Java 8, les classes anonymes étaient le seul moyen de garantir que les classes étaient définies à la volée et instanciées immédiatement. Le but des classes anonymes était de réduire le passe-partout et de fournir un moyen court et simple de représenter les classes sous forme d'enregistrement. Jetons un coup d'œil à la manière typique à l'ancienne de générer un nouveau thread en Java :
package com.javacodegeeks.advanced.design;

public class AnonymousClass {
    public static void main( String[] args ) {
        new Thread(
            // Example of creating anonymous class which implements
            // Runnable interface
            new Runnable() {
                @Override
                public void run() {
                    // Implementation here
                }
            }
        ).start();
    }
}
Dans cet exemple, l'implémentation de Runnablel'interface est fournie immédiatement en tant que classe anonyme. Bien qu'il existe certaines limitations associées aux classes anonymes, les principaux inconvénients de leur utilisation sont la syntaxe de construction très détaillée à laquelle Java en tant que langage est obligé. Même une classe anonyme qui ne fait rien nécessite au moins 5 lignes de code à chaque fois qu'elle est écrite.
new Runnable() {
   @Override
   public void run() {
   }
}
Heureusement, avec Java 8, lambda et les interfaces fonctionnelles, tous ces stéréotypes disparaîtront bientôt et l'écriture de code Java aura enfin l'air vraiment concise.
package com.javacodegeeks.advanced.design;

public class AnonymousClass {
    public static void main( String[] args ) {
        new Thread( () -> { /* Implementation here */ } ).start();
    }
}

8. VISIBILITÉ

Nous avons déjà parlé un peu des règles de visibilité et d'accessibilité en Java dans la première partie du tutoriel. Dans cette partie, nous allons revenir sur ce sujet, mais dans le contexte du sous-classement. Conception de classes et d'interfaces (Traduction de l'article) - 2La visibilité à différents niveaux permet ou empêche les classes de voir d'autres classes ou interfaces (par exemple, si elles sont dans des packages différents ou imbriquées les unes dans les autres) ou des sous-classes de voir et d'accéder aux méthodes, constructeurs et champs de leurs parents. Dans la section suivante, l'héritage, nous verrons cela en action.

9. HÉRITAGE

L'héritage est l'un des concepts clés de la programmation orientée objet, servant de base à la construction d'une classe de relations. Combiné avec des règles de visibilité et d'accessibilité, l'héritage permet de concevoir les classes dans une hiérarchie qui peut être étendue et maintenue. Au niveau conceptuel, l'héritage en Java est implémenté à l'aide du sous-classement et du mot-clé extends , ainsi que de la classe parent. Une sous-classe hérite de tous les éléments publics et protégés de la classe parent. De plus, une sous-classe hérite des éléments privés du package de sa classe parent si les deux (sous-classe et classe) se trouvent dans le même package. Cela étant dit, il est très important, peu importe ce que vous essayez de concevoir, de s'en tenir à l'ensemble minimum de méthodes qu'une classe expose publiquement ou à ses sous-classes. Par exemple, regardons la classe Parentet sa sous-classe Childpour démontrer la différence de niveaux de visibilité et leurs effets.
package com.javacodegeeks.advanced.design;

public class Parent {
    // Everyone can see it
    public static final String CONSTANT = "Constant";

    // No one can access it
    private String privateField;
    // Only subclasses can access it
    protected String protectedField;

    // No one can see it
    private class PrivateClass {
    }

    // Only visible to subclasses
    protected interface ProtectedInterface {
    }

    // Everyone can call it
    public void publicAction() {
    }

    // Only subclass can call it
    protected void protectedAction() {
    }

    // No one can call it
    private void privateAction() {
    }

    // Only subclasses in the same package can call it
    void packageAction() {
    }
}
package com.javacodegeeks.advanced.design;

// Resides in the same package as parent class
public class Child extends Parent implements Parent.ProtectedInterface {
    @Override
    protected void protectedAction() {
        // Calls parent's method implementation
        super.protectedAction();
    }

    @Override
    void packageAction() {
        // Do nothing, no call to parent's method implementation
    }

    public void childAction() {
        this.protectedField = "value";
    }
}
L'héritage est un sujet très vaste en soi, avec de nombreux détails spécifiques à Java. Cependant, il existe quelques règles faciles à suivre et qui peuvent grandement contribuer à conserver la brièveté de la hiérarchie des classes. En Java, chaque sous-classe peut remplacer toutes les méthodes héritées de son parent à moins qu'elle n'ait été déclarée finale. Cependant, il n’existe pas de syntaxe ou de mot-clé spécial pour marquer une méthode comme étant remplacée, ce qui peut prêter à confusion. C'est pourquoi l'annotation @Override a été introduite : chaque fois que votre objectif est de surcharger une méthode héritée, veuillez utiliser l' annotation @Override pour l'indiquer succinctement. Un autre dilemme auquel les développeurs Java sont constamment confrontés en matière de conception est la construction de hiérarchies de classes (avec des classes concrètes ou abstraites) par rapport à l'implémentation d'interfaces. Nous recommandons fortement de privilégier les interfaces plutôt que les classes ou les classes abstraites lorsque cela est possible. Les interfaces sont plus légères, plus faciles à tester et à maintenir, et minimisent également les effets secondaires des modifications de mise en œuvre. De nombreuses techniques de programmation avancées, telles que la création de classes proxy dans la bibliothèque standard Java, s'appuient fortement sur les interfaces.

10. HÉRITAGE MULTIPLE

Contrairement au C++ et à certains autres langages, Java ne prend pas en charge l'héritage multiple : en Java, chaque classe ne peut avoir qu'un seul parent direct (la classe étant Objectau sommet de la hiérarchie). Cependant, une classe peut implémenter plusieurs interfaces et l'empilement d'interfaces est donc le seul moyen d'obtenir (ou de simuler) un héritage multiple en Java.
package com.javacodegeeks.advanced.design;

public class MultipleInterfaces implements Runnable, AutoCloseable {
    @Override
    public void run() {
        // Some implementation here
    }

    @Override
    public void close() throws Exception {
       // Some implementation here
    }
}
L'implémentation de plusieurs interfaces est en fait assez puissante, mais souvent la nécessité d'utiliser l'implémentation encore et encore conduit à une hiérarchie de classes profonde comme moyen de surmonter le manque de prise en charge par Java de l'héritage multiple. 
public class A implements Runnable {
    @Override
    public void run() {
        // Some implementation here
    }
}
// Class B wants to inherit the implementation of run() method from class A.
public class B extends A implements AutoCloseable {
    @Override
    public void close() throws Exception {
       // Some implementation here
    }
}
// Class C wants to inherit the implementation of run() method from class A
// and the implementation of close() method from class B.
public class C extends B implements Readable {
    @Override
    public int read(java.nio.CharBuffer cb) throws IOException {
       // Some implementation here
    }
}
Et ainsi de suite... La récente version de Java 8 résout quelque peu le problème de l'injection de méthode par défaut. En raison des méthodes par défaut, les interfaces fournissent en réalité non seulement un contrat, mais également une implémentation. Par conséquent, les classes qui implémentent ces interfaces hériteront également automatiquement de ces méthodes implémentées. Par exemple:
package com.javacodegeeks.advanced.design;

public interface DefaultMethods extends Runnable, AutoCloseable {
    @Override
    default void run() {
        // Some implementation here
    }

    @Override
    default void close() throws Exception {
       // Some implementation here
    }
}

// Class C inherits the implementation of run() and close() methods from the
// DefaultMethods interface.
public class C implements DefaultMethods, Readable {
    @Override
    public int read(java.nio.CharBuffer cb) throws IOException {
       // Some implementation here
    }
}
Gardez à l’esprit que l’héritage multiple est un outil très puissant, mais en même temps dangereux. Le problème bien connu du Diamant de la Mort est souvent cité comme un défaut majeur dans la mise en œuvre de l'héritage multiple, obligeant les développeurs à concevoir très soigneusement les hiérarchies de classes. Malheureusement, les interfaces Java 8 avec les méthodes par défaut sont également victimes de ces défauts.
interface A {
    default void performAction() {
    }
}

interface B extends A {
    @Override
    default void performAction() {
    }
}

interface C extends A {
    @Override
    default void performAction() {
    }
}
Par exemple, l'extrait de code suivant ne pourra pas être compilé :
// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}
À ce stade, il est juste de dire que Java, en tant que langage, a toujours essayé d'éviter les cas extrêmes de la programmation orientée objet, mais à mesure que le langage évolue, certains de ces cas ont soudainement commencé à apparaître. 

11. HÉRITAGE ET COMPOSITION

Heureusement, l’héritage n’est pas le seul moyen de concevoir votre classe. Une autre alternative que de nombreux développeurs considèrent comme bien meilleure que l’héritage est la composition. L’idée est très simple : au lieu de créer une hiérarchie de classes, il faut les composer d’autres classes. Regardons cet exemple :
// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}
La classe Vehiclese compose d’un moteur et de roues (ainsi que de nombreuses autres pièces laissées de côté par souci de simplicité). Cependant, on peut dire qu'une classe Vehicleest aussi un moteur, elle peut donc être conçue en utilisant l'héritage. 
public class Vehicle extends Engine {
    private Wheels[] wheels;
    // ...
}
Quelle solution de conception serait correcte ? Les lignes directrices générales de base sont connues sous le nom de principes IS-A (est) et HAS-A (contient). IS-A est une relation d'héritage : une sous-classe satisfait également à la spécification de classe de la classe parent et une variation de la classe parent. sous-classe) étend son parent. Si vous voulez savoir si une entité en étend une autre, effectuez un test de correspondance - IS -A (est).") Par conséquent, HAS-A est une relation de composition : une classe possède (ou contient) un objet qui. Dans la plupart des cas, le principe HAS-A fonctionne mieux que IS-A pour un certain nombre de raisons : 
  • La conception est plus flexible ;
  • Le modèle est plus stable car le changement ne se propage pas à travers la hiérarchie des classes ;
  • Une classe et sa composition sont faiblement couplées par rapport à la composition, qui couple étroitement un parent et sa sous-classe.
  • La suite logique de la pensée dans une classe est plus simple, puisque toutes ses dépendances y sont incluses, en un seul endroit. 
Quoi qu’il en soit, l’héritage a sa place et résout un certain nombre de problèmes de conception existants de diverses manières ; il ne faut donc pas le négliger. Veuillez garder ces deux alternatives à l'esprit lors de la conception de votre modèle orienté objet.

12. ENCAPSULATION.

Le concept d'encapsulation dans la programmation orientée objet consiste à cacher tous les détails d'implémentation (comme le mode de fonctionnement, les méthodes internes, etc.) au monde extérieur. Les avantages de l'encapsulation sont la maintenabilité et la facilité de changement. L'implémentation interne de la classe est cachée, le travail avec les données de la classe se fait exclusivement via les méthodes publiques de la classe (un vrai problème si vous développez une bibliothèque ou un framework utilisé par de nombreuses personnes). L'encapsulation en Java est réalisée grâce à des règles de visibilité et d'accessibilité. En Java, il est considéré comme une bonne pratique de ne jamais exposer les champs directement, uniquement via des getters et des setters (sauf si les champs sont marqués comme final). Par exemple:
package com.javacodegeeks.advanced.design;

public class Encapsulation {
    private final String email;
    private String address;

    public Encapsulation( final String email ) {
        this.email = email;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getEmail() {
        return email;
    }
}
Cet exemple n'est pas sans rappeler ce qu'on appelle les JavaBeans dans le langage Java : les classes Java standards sont écrites selon un ensemble de conventions, dont l'une permet d'accéder aux champs uniquement à l'aide des méthodes getter et setter. Comme nous l'avons déjà souligné dans la section héritage, veuillez toujours respecter le contrat minimum de publicité dans une classe, en utilisant les principes d'encapsulation. Tout ce qui ne devrait pas être public doit devenir privé (ou protégé/package privé, selon le problème que vous résolvez). Cela sera payant à long terme en vous donnant la liberté de concevoir sans (ou du moins en minimisant) les modifications brutales. 

13. COURS FINAUX ET MÉTHODES

En Java, il existe un moyen d'empêcher une classe de devenir une sous-classe d'une autre classe : l'autre classe doit être déclarée finale. 
package com.javacodegeeks.advanced.design;

public final class FinalClass {
}
Le même mot-clé final dans une déclaration de méthode empêche les sous-classes de remplacer la méthode. 
package com.javacodegeeks.advanced.design;

public class FinalMethod {
    public final void performAction() {
    }
}
Il n’existe pas de règles générales pour décider si une classe ou une méthode doit être définitive ou non. Les classes et méthodes finales limitent l'extensibilité et il est très difficile de prévoir si une classe doit ou non être héritée, ou si une méthode doit ou non être remplacée à l'avenir. Ceci est particulièrement important pour les développeurs de bibliothèques, car de telles décisions de conception pourraient limiter considérablement l'applicabilité de la bibliothèque. La bibliothèque standard Java propose plusieurs exemples de classes finales, la plus connue étant la classe String. À un stade précoce, cette décision a été prise pour empêcher toute tentative des développeurs de proposer leur propre « meilleure » solution pour implémenter les chaînes. 

14. QUELLE EST LA SUITE

Dans cette partie de la leçon, nous avons abordé les concepts de programmation orientée objet en Java. Nous avons également jeté un coup d'œil rapide à la programmation contractuelle, en abordant certains concepts fonctionnels et en voyant comment le langage a évolué au fil du temps. Dans la prochaine partie de la leçon, nous aborderons les génériques et comment ils changent la façon dont nous abordons la sécurité des types en programmation. 

15. TÉLÉCHARGER LE CODE SOURCE

Vous pouvez télécharger la source ici - advanced-java-part-3 Source : Comment concevoir des classes et
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION