2 votes

Ce modèle de définition de la classe et du constructeur est-il trop redondant ?

Je rencontre souvent un schéma similaire à celui-ci :

class Person {
    public string firstName, lastName;
    public Person(string firstName, string lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

Cela me semble excessivement redondant (j'imagine qu'il suffirait de taper "prénom" une fois au lieu de trois ), mais je ne vois pas d'autre solution. Des idées ? Peut-être ne suis-je pas au courant d'un certain modèle de conception que je devrais utiliser ici ?

Edit - Je pense qu'il faut que je développe un peu. Je ne demande pas comment rendre le code de l'exemple "meilleur", mais plutôt "plus court". Dans son état actuel, tous les noms de membres apparaissent 4 fois (déclaration, initialisation, arguments du constructeur), et cela semble plutôt redondant. Je me demande donc s'il existe un modèle (ou un sucre sémantique) permettant d'obtenir (grosso modo) le même comportement, mais avec moins de gonflement.
Je m'excuse d'avoir manqué de clarté au départ.

Edit - L'exemple d'initialisation C# 3.0 de Dave est très intéressant, mais j'espère toujours une réponse plus générale :)

Edit - Je me rends compte maintenant que certains langages permettent des implémentations moins verbeuses ; Java et C# ne le permettent peut-être pas.

4voto

Dave Downs Points 4677

Cela dépend de ce que vous essayez d'accomplir et si ces valeurs particulières avoir doit être défini pour une raison quelconque lors de la création de l'objet.

Si vous souhaitez que seules les valeurs conservées soient définies lors de la construction, vous devez déclarer la classe comme vous l'avez fait :

class Person
{
    public string FirstName { get; private set; }
    public string Surname { get; private set; }

    public Person(string firstName, string surname)
    {
        // properties are read-only so must be set as part of the constructor
        this.FirstName = firstName;
        this.Surname = surname;
    }
}

Si les propriétés doivent être définies lors de la construction, vous devez également définir la classe comme vous l'avez fait. Toutefois, vous pouvez également faire en sorte qu'il soit possible de modifier ces valeurs ultérieurement.

class Person
{
    public string FirstName { get; set; }
    public string Surname { get; set; }

    public Person(string firstName, string surname)
    {            
        this.FirstName = firstName;
        this.Surname = surname;
    }
}

Si les propriétés peuvent être définies à tout moment, c'est-à-dire qu'il est facultatif de les définir lors de la création, il n'est pas nécessaire de les transmettre dans le cadre du constructeur.

class Person
{
    public string FirstName { get; set; }
    public string Surname { get; set; }

    public Person()
    {
    }
}

En C# (à partir de la version 3), vous pouvez toujours définir ces propriétés lors de la création, mais je ne sais pas quelles sont les caractéristiques des autres langages qui pourraient refléter cela :

var myPerson = new Person
{
    FirstName = "Test",
    Surname = "Test2",
};

Les exemples sont tous en C# mais devraient être valables pour la POO en général.

1voto

Don Roby Points 24965

Je ne demande pas comment rendre le code de l'exemple "meilleur", mais plutôt "plus court". Dans son état actuel, tous les noms de membres apparaissent 4 fois (déclaration, initialisation, arguments du constructeur), et cela semble plutôt redondant. Je me demande donc s'il existe un modèle (ou un sucre sémantique) permettant d'obtenir (grosso modo) le même comportement, mais avec moins de gonflement.

Il n'y a pas vraiment de modèle de conception à ma connaissance, mais l'importance de cette répétition varie considérablement d'une langue à l'autre.

Par exemple, en Scala, vous pourriez définir ceci comme une classe de cas, et perdre toutes les répétitions :

case class Person(firstName: String, lastName: String)

De même, en Ruby, il est possible de raccourcir la définition d'une classe en utilisant des accesseurs d'attributs :

class Person
  attr_accessor :first_name, :last_name
end

Aucun des deux n'est précisément équivalent à ce que vous avez décrit, avec des variations selon qu'ils définissent des objets mutables ou l'initialisation. Mais ce type de redondance dépend très certainement de la langue.

1voto

Jörg W Mittag Points 153275

Le modèle général est probablement "utiliser un bon langage de programmation". Par exemple, cette simple ligne de Scala est à peu près équivalente à ce que vous avez écrit ci-dessus :

class Person(var firstName: String, var lastName: String)

Vous pouvez exécuter un décompilateur Java sur le fichier généré. Person.class pour voir ce qu'il faudrait écrire en Java pour obtenir la même fonctionnalité :

public class Person {
    private String firstName, lastName;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String paramString) {
        this.firstName = paramString;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String paramString) {
        this.lastName = paramString;
    }

    public Person(String firstName, String lastName) {
        setFirstName(firstName);
        setLastName(lastName);
    }
}

Les noms des méthodes seront légèrement différents (au lieu de getFirstName y setFirstName Scala utilise seulement firstName y firstName_= ce dernier étant à son tour codé en tant que firstName_$eq (puisque c'est illégal en Java), mais l'intention est la même.

Si vous pouvez faire de votre classe un case class vous obtiendrez également des implémentations correctes générées automatiquement pour equals y hashCode également.

En Ruby, vous écririez :

Person = Struct.new(:first_name, :last:name)

et vous obtiendrez à nouveau quelque chose d'assez similaire à ce que vous obtiendriez dans votre exemple Java. Struct.new synthétisera en fait une classe appropriée qui ressemblera à peu près à ceci :

class Person
  attr_accessor :first_name, :last_name

  def initialize(first_name, last_name)
    self.first_name, self.last_name = first_name, last_name
  end
end

0voto

Waquo Points 780

Certains langages sont conçus pour être verbeux et ne permettent généralement pas d'y remédier.

En ce qui concerne les déclarations de type, Java vous oblige non seulement à énoncer, mais aussi à répéter l'évidence. L'inférence de type peut en grande partie résoudre ce problème, si vous êtes prêt à utiliser des langages comme Scala.

En Javascript, où il n'y a ni types statiques ni classes, les constructeurs sont simplement des fonctions qui produisent des objets :

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X