10
votes

Composition: Utiliser des traits pour éviter les fonctions de transfert?

Disons que nous avons deux classes, A code> et b code>. Lors de l'utilisation de la composition pour modéliser un "a-a-a" em> ou "est-mise en œuvre de" em> relation (par exemple, B code> a-A-A em> A code>), l'un des inconvénients par rapport à l'héritage est que B code> ne contient pas la fonctionnalité publique de A code> que cela nécessite. Afin d'accéder aux fonctions publiques code> A code>, il est nécessaire de fournir des fonctions de transfert (par opposition à l'héritage, où b code> hériterait de tout a CODE> S FONCTIONS PUBLIQUES).

Pour donner un exemple plus concret, disons que nous avons une personne personne code> quel a-a-a-a-a em> contactInfo code>: P>

using namespace std;

class ContactInfo
{
public:
   ContactInfo();
   void updateAddress(string address);
   void updatePhone(string phone);
   void updateEmail(string email);
private:
   string address;
   string phone;
   string email;
};

class Person
{
public:
   Person();
   // Forwarding functions:
   void updateAddress(string address){contactInfo.updateAddress(address)};
   void updatePhone(string phone){contactInfo.updatePhone(phone)};
   void updateEmail(string email){contactInfo.updateEmail(email)};
private:
   ContactInfo contactInfo;
};


8 commentaires

Je pense que Wikipedia vous trompe à ce sujet. Les traits sont un outil de programmation générique, disons que vous vouliez contenir contactInfo de certains types de paramètres de type de modèle.


"A une" relation est une relation "a une" relation. Il n'y a pas de "exemples artificiels" car en cas de sitaution, il est possible de résoudre le problème de décider si quelque chose est quelque chose ou que cela a quelque chose. Si vous êtes incapable de résoudre cela, vous vous trompez ailleurs. Un exemple délicat serait comme ceci: une voiture est un véhicule, un aéronef est un véhicule, de sorte que vous entraîne un véhicule? La réponse est non. Les trains sont un ensemble de véhicules (le moteur avant, les wagons, qui peuvent également bouger et éventuellement le véhicule arrière). Vous devez toujours faire des distinctions claires, sinon vous aurez des problèmes.


Je ne trouve pas cet article Wikipedia Good: - /


@ Lukasz1985 Merci, mais ma question n'était pas sur la différence de différencie entre "a un" et "est un", c'était à propos des traits.


Je ne pense pas que vous devriez utiliser des traits pour que votre travail soit plus facile. Vous déconnectez probablement la composition car dans votre exemple, vous devriez pouvoir obtenir l'objet sous-jacent en utilisant la classe contenant (comme personne-> getcontactinfo ()). La bonne chose n'est pas d'utiliser des traits et une héritage multiple en premier. Et si cela reste de cette façon, le seul thats est laissé, c'est la question de la perte entre héritage et composition (est une ou a a). Vous pouvez regarder ma réponse ici: Stackoverflow.com/ Questions / 49002 / ...


Vous ne pouvez pas décider de ces choses arbitraires, "préférer une chose sur l'autre", la citation: >>> Un inconvénient à l'utilisation de la composition à la place de l'héritage est que toutes les méthodes fournies par les classes composées doivent être mises en œuvre dans le dérivé. classe, même s'ils ne sont que des méthodes de transmission. [...] Cet inconvénient peut être évité à l'aide de traits. <<< est ridicule car la composition (a) et l'héritage (est a) ne peut être comparée aux autres. Les traits ne peuvent que mettre beaucoup d'enterrer sur votre code le rendant très aléatoire et chaotique (trait ici, trait là-bas, trait partout).


@ Lukasz1985 Comme je l'ai dit, ma question n'est pas sur la manière de décider ou de préférer une méthode sur une autre. J'ai précisément dit que mon exemple est conçu pour que les gens ne le nitpicent pas (c'est-à-dire que mon exemple est un bon candidat à la composition - c'est juste une mise en place pour mener à ma question). Mais j'apprécie vos commentaires concernant les traits.


Je vous raconterai une dernière chose: OOP est un paradigme de programmation dans lequel des traits, héritage mutliples et interfaces (interfaces - à quelques exceptions près) n'ont pas le droit d'exister. Si vous les utilisez, cela vous paiera plus tard très douloureusement.


4 Réponses :


2
votes

Peut-être que vous pouvez essayer un héritage privé:

class Person : private ContactInfo
{
public:
   Person() { }
   using ContactInfo::updateAddress;
   using ContactInfo::updatePhone;
   using ContactInfo::updateEmail;
};

int main()
{
    Person person;
    person.updateAddress("hi");
    return 0;
}


0 commentaires

0
votes

afaik une classe de trait est comme suit:

#include <iostream>
using namespace std;

class ContactInfo
{
public:
   void updateAddress() { cout << "update address"; };
   void updatePhone() {};
   void updateEmail() {};
};

template<class T> class TraitClass
{
  public:

  private:
    T obj;
};

template<> class TraitClass<ContactInfo>
{
  public:
        void updateAddress() {obj.updateAddress();};
        void updatePhone() {obj.updatePhone();};
        void updateEmail() {obj.updateEmail();};
  private:
    ContactInfo obj;
};

class Person
{
public:
        void updateAddress() {obj.updateAddress();};
        void updatePhone() {obj.updatePhone();};
        void updateEmail() {obj.updateEmail();};
private:
    TraitClass<ContactInfo> obj;
};

int main() {

    Person myPerson;

    myPerson.updateAddress();

    return 0;
}


0 commentaires

2
votes

L'article parle de l'héritage avec interface ,

Ainsi, il indique que l'objet doit respecter certaines signatures.

Type Types peut être utilisé pour vérifier si La signature est correcte et expédiez la fonction appropriée

par exemple certains algorithmes stl attendre le type itérateur , Mais ces itérateurs n'héritent pas d'un itérateur mais doivent fournir un contrat ( opérateur ++ () , opérateur! = (RHS) , opérateur * () ).

avec l'article Article:

  • lecteur de classe - qui peut déplacer
  • Bâtiment de classe - qui ne peut pas bouger

    et code: xxx


0 commentaires

1
votes

Tout d'abord, je devrais mentionner que les traits sont des choses différentes dans C ++ / STL et des langues comme PHP, Lasso, etc. On dirait que l'article de Wikipedia fait référence à des traits de type PHP car c ++ / stl Les traits ne sont pas conçus pour la réutilisation polymorphe (Nous parlons de la réutilisation du code avec un comportement polymorphique, non?). Ils ont conçu pour simplifier la déclaration de classes de modèles.

Les traits sont utilisés dans certaines langues qui ne prennent pas en charge plusieurs héritages (PHP, Lasso, etc.). Les traits permettent de "émuler" héritage multiple (mais de multiples héritages et de traits ne sont pas exactement les mêmes).

en contraste C ++ ne prend pas en charge PHP-traits mais prend en charge plusieurs héritages. Donc, si vous parlez de la solution de C ++ puis une solution de type Trait sera quelque chose comme ceci: xxx

afin de répondre à votre question

Comment allez-vous utiliser des traits pour éviter les fonctions de transfert avec composition?

1) Les traits ne peuvent pas éviter les fonctions de transfert avec la composition, car les traits fonctionnent indépendamment de la composition. (L'article de WikiPadia est un peu lié à la relation entre les traits et la composition)
2) Les traits de type PHP / Lasso peuvent être partiellement émulés en C ++ avec de multiples héritage.


2 commentaires

Merci d'avoir fourni une réponse qui répond directement à ma question.


@Jbentley, traits en C ++ peuvent être utilisés afin de fournir une meilleure transmission avec la composition. Voir ma question associée ici: Stackoverflow.com/Questtions/28393195/...