web-dev-qa-db-fra.com

Pourquoi Java n'offre-t-il pas une surcharge d'opérateur?

Venant du C++ vers Java, la question qui reste sans réponse est la suivante: pourquoi Java n’a-t-il pas inclus la surcharge d’opérateurs?

Complex a, b, c; a = b + c; n'est-il pas beaucoup plus simple que Complex a, b, c; a = b.add(c);?

Existe-t-il une raison connue à cela, des arguments valides pour non permettant la surcharge de l’opérateur? La raison est-elle arbitraire ou perdue dans le temps?

375
rengolin

En supposant que vous vouliez écraser la valeur précédente de l'objet référencé par a, une fonction membre devrait alors être appelée.

Complex a, b, c;
// ...
a = b.add(c);

En C++, cette expression indique au compilateur de créer trois (3) objets sur la pile, d'effectuer l'addition et copier la valeur résultante de l'objet temporaire dans l'objet existant a.

Cependant, en Java, operator= n'effectue pas de copie de valeur pour les types de référence et les utilisateurs peuvent uniquement créer de nouveaux types de référence, pas de types de valeur. Ainsi, pour un type défini par l'utilisateur nommé Complex, affectation signifie copier une référence à une valeur existante.

Considérons plutôt:

b.set(1, 0); // initialize to real number '1'
a = b; 
b.set(2, 0);
assert( !a.equals(b) ); // this assertion will fail

En C++, cela copie la valeur, de sorte que la comparaison ne sera pas égale. En Java, operator= effectue une copie de référence, si bien que a et b font maintenant référence à la même valeur. En conséquence, la comparaison produira «égal», puisque l'objet se comparera égal à lui-même.

La différence entre les copies et les références ne fait qu'ajouter à la confusion de la surcharge de l'opérateur. Comme @Sebastian l'a mentionné, Java et C # doivent tous deux traiter séparément l'égalité des valeurs et des références - operator+ traiterait probablement des valeurs et des objets, mais operator= est déjà implémenté pour gérer les références.

En C++, vous ne devriez avoir affaire qu'à un type de comparaison à la fois, ce qui peut être moins déroutant. Par exemple, sur Complex, operator= et operator== travaillent tous deux sur des valeurs - en copiant des valeurs et en comparant des valeurs, respectivement.

17
Aaron

Beaucoup de messages se plaignent de la surcharge de l'opérateur.

Je sentais que je devais clarifier les concepts de "surcharge de l'opérateur", offrant un point de vue alternatif sur ce concept.

Code obscurcissant?

Cet argument est une erreur.

Le masquage est possible dans toutes les langues ...

Il est aussi facile de masquer du code en C ou Java via des fonctions/méthodes qu'en C++ via des surcharges d’opérateurs:

// C++
T operator + (const T & a, const T & b) // add ?
{
   T c ;
   c.value = a.value - b.value ; // subtract !!!
   return c ;
}

// Java
static T add (T a, T b) // add ?
{
   T c = new T() ;
   c.value = a.value - b.value ; // subtract !!!
   return c ;
}

/* C */
T add (T a, T b) /* add ? */
{
   T c ;
   c.value = a.value - b.value ; /* subtract !!! */
   return c ;
}

... même dans les interfaces standard de Java

Pour un autre exemple, voyons le Cloneable interface en Java:

Vous êtes censé cloner l'objet implémentant cette interface. Mais tu pourrais mentir. Et créez un objet différent. En fait, cette interface est tellement faible que vous pourriez retourner un autre type d'objet, juste pour le plaisir:

class MySincereHandShake implements Cloneable
{
    public Object clone()
    {
       return new MyVengefulKickInYourHead() ;
    }
}

Comme l'interface Cloneable peut être abusée/obscurcie, devrait-elle être interdite pour les mêmes motifs que la surcharge d'opérateurs C++ est supposée l'être?

Nous pourrions surcharger la méthode toString() d'une classe MyComplexNumber pour qu'elle renvoie l'heure du jour sous forme de chaîne. La surcharge toString() doit-elle également être bannie? Nous pourrions saboter MyComplexNumber.equals pour qu'il renvoie une valeur aléatoire, modifie les opérandes, etc., etc., etc.

En Java, comme en C++ ou dans un langage quelconque, le programmeur doit respecter un minimum de sémantique lors de l'écriture de code. Cela signifie qu’il faut implémenter une fonction add qui ajoute, et une méthode d’implémentation Cloneable qui clone et un opérateur ++ qui incrémente.

Qu'est-ce qui brouille de toute façon?

Maintenant que nous savons que le code peut être saboté même via les méthodes primitives Java, nous pouvons nous interroger sur l'utilisation réelle de la surcharge d'opérateurs en C++?

Notation claire et naturelle: méthodes vs surcharge d’opérateurs?

Nous comparerons ci-dessous, pour différents cas, le "même" code dans Java et C++, pour avoir une idée du type de style de codage le plus clair.

Comparaisons naturelles:

// C++ comparison for built-ins and user-defined types
bool    isEqual          = A == B ;
bool    isNotEqual       = A != B ;
bool    isLesser         = A <  B ;
bool    isLesserOrEqual  = A <= B ;

// Java comparison for user-defined types
boolean isEqual          = A.equals(B) ;
boolean isNotEqual       = ! A.equals(B) ;
boolean isLesser         = A.comparesTo(B) < 0 ;
boolean isLesserOrEqual  = A.comparesTo(B) <= 0 ;

Veuillez noter que A et B peuvent être de n'importe quel type en C++, à condition que les surcharges d'opérateur soient fournies. En Java, lorsque A et B ne sont pas des primitives, le code peut devenir très déroutant, même pour des objets de type primitif (BigInteger, etc.) ...

Accesseurs de tableaux/conteneurs naturels et souscription:

// C++ container accessors, more natural
value        = myArray[25] ;         // subscript operator
value        = myVector[25] ;        // subscript operator
value        = myString[25] ;        // subscript operator
value        = myMap["25"] ;         // subscript operator
myArray[25]  = value ;               // subscript operator
myVector[25] = value ;               // subscript operator
myString[25] = value ;               // subscript operator
myMap["25"]  = value ;               // subscript operator

// Java container accessors, each one has its special notation
value        = myArray[25] ;         // subscript operator
value        = myVector.get(25) ;    // method get
value        = myString.charAt(25) ; // method charAt
value        = myMap.get("25") ;     // method get
myArray[25]  = value ;               // subscript operator
myVector.set(25, value) ;            // method set
myMap.put("25", value) ;             // method put

En Java, on voit que pour que chaque conteneur fasse la même chose (accéder à son contenu via un index ou un identifiant), nous avons une façon de le faire différente, ce qui est déroutant.

En C++, chaque conteneur utilise la même manière d'accéder à son contenu, grâce à la surcharge de l'opérateur.

Manipulation naturelle avancée de types

Les exemples ci-dessous utilisent un objet Matrix, trouvé à l'aide des premiers liens trouvés sur Google pour " objet Java Matrix " et " objet c ++ Matrix ":

// C++ YMatrix matrix implementation on CodeProject
// http://www.codeproject.com/KB/architecture/ymatrix.aspx
// A, B, C, D, E, F are Matrix objects;
E =  A * (B / 2) ;
E += (A - B) * (C + D) ;
F =  E ;                  // deep copy of the matrix

// Java JAMA matrix implementation (seriously...)
// http://math.nist.gov/javanumerics/jama/doc/
// A, B, C, D, E, F are Matrix objects;
E = A.times(B.times(0.5)) ;
E.plusEquals(A.minus(B).times(C.plus(D))) ;
F = E.copy() ;            // deep copy of the matrix

Et cela ne se limite pas aux matrices. Les classes BigInteger et BigDecimal de Java ont le même contenu confus, alors que leurs équivalents en C++ sont aussi clairs que les types intégrés.

Itérateurs naturels:

// C++ Random Access iterators
++it ;                  // move to the next item
--it ;                  // move to the previous item
it += 5 ;               // move to the next 5th item (random access)
value = *it ;           // gets the value of the current item
*it = 3.1415 ;          // sets the value 3.1415 to the current item
(*it).foo() ;           // call method foo() of the current item

// Java ListIterator<E> "bi-directional" iterators
value = it.next() ;     // move to the next item & return the value
value = it.previous() ; // move to the previous item & return the value
it.set(3.1415) ;        // sets the value 3.1415 to the current item

Foncteurs naturels:

// C++ Functors
myFunctorObject("Hello World", 42) ;

// Java Functors ???
myFunctorObject.execute("Hello World", 42) ;

Concaténation de texte:

// C++ stream handling (with the << operator)
                    stringStream   << "Hello " << 25 << " World" ;
                    fileStream     << "Hello " << 25 << " World" ;
                    outputStream   << "Hello " << 25 << " World" ;
                    networkStream  << "Hello " << 25 << " World" ;
anythingThatOverloadsShiftOperator << "Hello " << 25 << " World" ;

// Java concatenation
myStringBuffer.append("Hello ").append(25).append(" World") ;

Ok, dans Java, vous pouvez aussi utiliser MyString = "Hello " + 25 + " World" ; ... Mais attendez une seconde: ceci est une surcharge d'opérateur, n'est-ce pas? N'est-ce pas tricher ???

:-RÉ

Code générique?

Les mêmes opérandes de modification de code générique doivent être utilisables à la fois pour les primitives intégrées (qui n'ont pas d'interface en Java), les objets standard (qui ne pourraient pas avoir la bonne interface) et les objets définis par l'utilisateur.

Par exemple, calculer la valeur moyenne de deux valeurs de types arbitraires:

// C++ primitive/advanced types
template<typename T>
T getAverage(const T & p_lhs, const T & p_rhs)
{
   return (p_lhs + p_rhs) / 2 ;
}

int     intValue     = getAverage(25, 42) ;
double  doubleValue  = getAverage(25.25, 42.42) ;
complex complexValue = getAverage(cA, cB) ; // cA, cB are complex
Matrix  matrixValue  = getAverage(mA, mB) ; // mA, mB are Matrix

// Java primitive/advanced types
// It won't really work in Java, even with generics. Sorry.

Discuter de la surcharge de l'opérateur

Maintenant que nous avons vu des comparaisons justes entre le code C++ utilisant la surcharge d'opérateur et le même code en Java, nous pouvons maintenant parler de "surcharge d'opérateur" en tant que concept.

La surcharge des opérateurs existait depuis avant les ordinateurs

Même en dehors de l'informatique, il existe une surcharge d'opérateurs: par exemple, en mathématiques, des opérateurs tels que +, -, *, etc. sont surchargés.

En effet, la signification de +, -, *, etc., change en fonction des types d'opérandes (valeurs numériques, vecteurs, fonctions d'onde quantique, matrices, etc.).

La plupart d’entre nous, dans le cadre de nos cours de sciences, avons appris plusieurs significations pour les opérateurs, en fonction du type d’opérandes. Les avons-nous trouvés déroutants, eux?

La surcharge de l'opérateur dépend de ses opérandes

C’est la partie la plus importante de la surcharge des opérateurs: comme en mathématiques ou en physique, l’opération dépend du type de ses opérandes.

Alors, connaissez le type de l'opérande, et vous connaîtrez l'effet de l'opération.

Même C et Java ont une surcharge d'opérateur (codée en dur)

En C, le comportement réel d'un opérateur changera en fonction de ses opérandes. Par exemple, l'ajout de deux entiers est différent de l'ajout de deux doubles, voire d'un entier et d'un double. Il y a même tout le domaine arithmétique du pointeur (sans transtypage, vous pouvez ajouter à un pointeur un entier, mais vous ne pouvez pas ajouter deux pointeurs ...).

En Java, il n’existe pas d’arithmétique de pointeur, mais quelqu'un trouve toujours une concaténation de chaîne sans l'opérateur + serait assez ridicule pour justifier une exception dans le credo "une surcharge d'opérateur est mauvaise".

C’est juste que vous, en tant que C (pour des raisons historiques) ou Java (pour raisons personnelles, voir ci-dessous), vous ne pouvez pas fournir le vôtre.

En C++, la surcharge des opérateurs n’est pas facultative ...

En C++, la surcharge des opérateurs pour les types intégrés n’est pas possible (c’est une bonne chose), mais défini par l'utilisateur types peuvent avoir défini par l'utilisateur surcharge de l'opérateur.

Comme cela a déjà été dit précédemment, en C++, contrairement à Java, les types d'utilisateurs ne sont pas considérés comme des citoyens de seconde classe du langage, par rapport aux types intégrés. Ainsi, si les types intégrés ont des opérateurs, les types d'utilisateurs doivent également pouvoir les avoir.

La vérité est que, comme les méthodes toString(), clone(), equals() sont pour Java (c'est-à-dire de type quasi standard), La surcharge des opérateurs C++ fait tellement partie du C++ qu’elle devient aussi naturelle que les opérateurs C originaux, ou que les méthodes Java mentionnées précédemment.

Combinée à la programmation par modèle, la surcharge de l'opérateur devient un modèle de conception bien connu. En fait, vous ne pouvez pas aller très loin dans STL sans utiliser des opérateurs surchargés et des opérateurs surchargés pour votre propre classe.

... mais il ne faut pas en abuser

La surcharge de l'opérateur doit s'efforcer de respecter la sémantique de l'opérateur. Ne soustrayez pas dans un opérateur + (comme dans "ne soustrayez pas dans une fonction add" ou "restituez la merde dans une méthode clone").

La surcharge de casting peut être très dangereuse car elle peut conduire à des ambiguïtés. Ils devraient donc être réservés à des cas bien définis. En ce qui concerne && et ||, ne les surchargez jamais sauf si vous savez vraiment ce que vous faites, car vous perdrez l'évaluation du court-circuit que les opérateurs natifs && et || profiter.

Alors ... Ok ... Alors pourquoi ce n'est pas possible en Java?

Parce que James Gosling l'a dit:

J'ai laissé l'opérateur surchargé en tant que choix assez personnel parce que j'avais vu trop de gens en abuser en C++.

James Gosling. Source: http://www.gotw.ca/publications/c_family_interview.htm

Veuillez comparer le texte de Gosling ci-dessus avec celui de Stroustrup ci-dessous:

De nombreuses décisions en matière de conception C++ sont dues au fait que je n'aime pas forcer les gens à faire certaines choses [...] Souvent, j'ai été tenté d'interdire une fonctionnalité qui me déplaisait personnellement, je me suis abstenu de le faire parce que Je ne pensais pas avoir le droit d'imposer mon point de vue à d'autres.

Bjarne Stroustrup. Source: Conception et évolution de C++ (1.3 Contexte général)

La surcharge des opérateurs serait-elle bénéfique pour Java?

Certains objets bénéficieraient grandement de la surcharge de l'opérateur (types concrets ou numériques, tels que BigDecimal, nombres complexes, matrices, conteneurs, itérateurs, comparateurs, analyseurs syntaxiques, etc.).

En C++, vous pouvez profiter de cet avantage en raison de l'humilité de Stroustrup. En Java, vous êtes tout simplement foutu à cause de Gosling choix personnel.

Pourrait-il être ajouté à Java?

Les raisons pour lesquelles la surcharge d’opérateurs n’a pas été ajoutée maintenant dans Java pourraient être un mélange de politique interne, d’allergie à la fonctionnalité, de méfiance des développeurs (vous savez, les saboteurs qui semblent hanter Java équipes ...), compatibilité avec les machines virtuelles précédentes, temps nécessaire pour écrire une spécification correcte, etc.

Alors ne retenez pas votre souffle en attendant cette fonctionnalité ...

Mais ils le font en C # !!!

Ouais...

Bien que ce soit loin d'être la seule différence entre les deux langues, celle-ci ne manque jamais de m'amuser.

Apparemment, les gens de C #, avec leurs "chaque primitive est une struct, et une struct dérive d'un objet", a bien compris au premier essai.

Et ils le font en autres langues !!!

Malgré tous les FUD contre la surcharge d’opérateur définie utilisée, les langages suivants le supportent: Scala , Dart , Python , F # =, C # , D , ALGOL 68 , Smalltalk , Groovy , Perl 6 , C++, Ruby , Haskell , MATLAB , Eiffel , Lua , Clojure , Fortran 9 , Swift , Ada , Delphi 2005 ...

Tant de langues, avec tant de philosophies différentes (et parfois opposées), et pourtant elles sont toutes d'accord sur ce point.

Nourriture pour la pensée...

760
paercebal

James Gosling a comparé la conception de Java aux éléments suivants:

"Il existe ce principe de déménagement, lorsque vous passez d'un appartement à un autre. Une expérience intéressante consiste à emballer votre appartement et à le mettre dans des boîtes, puis à vous déplacer dans l'appartement suivant sans rien défaire jusqu'à ce que vous en ayez besoin. Vous faites votre premier repas et vous sortez quelque chose d’une boîte. Après un mois ou deux, vous vous en êtes servi pour déterminer à peu près tout ce dont vous avez réellement besoin dans votre vie, puis vous prenez le reste de la trucs - oublie combien tu aimes ou combien il est cool - et tu les jettes. C'est étonnant de voir comment cela simplifie ta vie, et tu peux utiliser ce principe dans toutes sortes de problèmes de conception: ne fais pas les choses simplement parce qu'elles êtes cool ou juste parce qu'ils sont intéressants. "

Vous pouvez lire le contexte de la citation ici

En gros, la surcharge par l'opérateur est idéale pour une classe qui modélise un type de point, une devise ou un nombre complexe. Mais après cela, vous commencez à manquer d'exemples rapidement.

L'abus de la fonctionnalité en C++ par les développeurs surchargeant les opérateurs tels que '&&', '||', les opérateurs de casting et bien sûr 'new'. La complexité résultant de la combinaison de cela avec pass par valeur et exceptions est bien décrite dans le livre Exceptionnel C++ .

39
Garth Gilmour

Découvrez les Boost.Units: link text

Il fournit une analyse dimensionnelle sans surcharge grâce à la surcharge de l'opérateur. Combien plus clair cela peut-il obtenir?

quantity<force>     F = 2.0*newton;
quantity<length>    dx = 2.0*meter;
quantity<energy>    E = F * dx;
std::cout << "Energy = " << E << endl;

produirait effectivement "Energy = 4 J", ce qui est correct.

20
user15793

Les concepteurs de Java ont décidé que la surcharge d’opérateurs posait plus de problèmes qu’elle ne valait la peine. Aussi simple que cela.

Dans un langage où chaque variable d'objet est en fait une référence, la surcharge de l'opérateur présente le risque supplémentaire d'être assez illogique, du moins pour un programmeur C++. Comparez la situation avec la surcharge de l'opérateur == de C # et les Object.Equals et Object.ReferenceEquals (ou le nom de celui-ci).

11
Sebastian Redl

Groovy est surchargé par l'opérateur et s'exécute dans la machine virtuelle Java. Si cela ne vous dérange pas, la performance (qui devient chaque jour plus petite). C'est automatique basé sur les noms de méthodes. Par exemple, "+" appelle la méthode "plus (argument)".

8
noah

Je pense que cela a peut-être été un choix de conception conscient pour obliger les développeurs à créer des fonctions dont le nom indique clairement leurs intentions. En C++, les développeurs surchargeaient les opérateurs avec des fonctionnalités qui n’auraient souvent aucun lien avec la nature communément admise de cet opérateur, ce qui rendrait presque impossible la détermination d’un morceau de code sans examiner sa définition.

6
user14128

Eh bien, vous pouvez vraiment vous tirer une balle dans le pied avec une surcharge de l'opérateur. C'est comme avec les pointeurs, les gens font des erreurs stupides avec eux et il a donc été décidé de prendre les ciseaux.

Au moins, je pense que c'est la raison… .. Je suis de votre côté quand même. :)

5
Sarien

Techniquement, chaque langage de programmation est surchargé par les opérateurs et peut traiter différents types de nombres, par exemple. nombres entiers et réels. Explication: Le terme surcharge signifie qu'il existe simplement plusieurs implémentations pour une fonction. Dans la plupart des langages de programmation, différentes implémentations sont fournies pour l'opérateur +, une pour les entiers, une pour les réels, on parle de surcharge de l'opérateur.

Or, de nombreuses personnes trouvent étrange que Java ait surchargé les opérateurs + pour l'ajout de chaînes. D'un point de vue mathématique, cela peut paraître étrange, mais vu du point de vue d'un développeur de langage de programmation, il n'y a rien de mal à ajouter une surcharge d'opérateur intégrée pour l'opérateur + pour d'autres classes, par exemple Chaîne. Cependant, la plupart des gens s'accordent pour dire qu'une fois que vous avez ajouté la surcharge intégrée pour + pour String, il est généralement conseillé de fournir cette fonctionnalité également au développeur.

Un complètement en désaccord avec l'erreur que la surcharge de l'opérateur obscurcisse le code, car c'est au développeur de décider. C'est naïf de penser, et pour être tout à fait honnête, ça vieillit.

+1 pour l'ajout d'une surcharge d'opérateur dans Java 8.

4
Olai

Dire que la surcharge de l'opérateur entraîne des erreurs logiques d'un type d'opérateur qui ne correspond pas à la logique de l'opération, c'est comme ne rien dire. Le même type d'erreur se produira si le nom de la fonction n'est pas approprié pour la logique d'opération - alors, quelle est la solution: abandonnez la possibilité d'utiliser la fonction !? C’est une réponse comique - "Convient pour la logique de fonctionnement", chaque nom de paramètre, chaque classe, fonction ou quoi que ce soit peut être logiquement inapproprié . Je pense que cette option devrait être disponible dans un langage de programmation respectable, et ceux qui pensent dangereux - hé non tous les deux dit que vous devez l'utiliser. Permet de prendre le C #. Ils ont laissé tomber les pointeurs, mais bon - il y a une déclaration de "code peu sûr" - programmez comme vous voudrez à vos risques et périls.

4
Kvant

Certaines personnes disent que la surcharge des opérateurs en Java conduirait à l'obscurcissement. Ces personnes ont-elles déjà cessé de regarder du code Java faire des calculs élémentaires, comme augmenter un pourcentage de la valeur financière avec BigDecimal? .... la verbosité d'un tel exercice devient sa propre démonstration d'obsfuscation. Ironiquement, l'ajout d'une surcharge d'opérateur à Java nous permettrait de créer notre propre classe Currency, ce qui rendrait ce code mathématique élégant et simple (moins obscurci).

3
Volksman

En supposant que Java soit le langage d'implémentation, alors a, b et c seraient tous des références au type Complex avec des valeurs initiales de null. En supposant également que Complex est immuable en tant que BigInteger mentionné et similaire immuable BigDecimal , je pense que vous voulez dire ce qui suit, car vous affectez la référence au Complexe renvoyée par l'ajout b et c, sans comparer cette référence à a.

N'est pas:

Complex a, b, c; a = b + c;

beaucoup plus simple que:

Complex a, b, c; a = b.add(c);
2
David Schlosnagle

Parfois, il serait bien d’avoir une surcharge d’opérateur, des classes d’ami et un héritage multiple.

Cependant, je pense toujours que c'était une bonne décision. Si Java avait eu une surcharge d'opérateur, nous ne pourrions jamais être sûrs de la signification de l'opérateur sans examiner le code source. Actuellement, ce n'est pas nécessaire. Et je pense que votre exemple d'utilisation de méthodes au lieu d'une surcharge d'opérateur est également très lisible. Si vous voulez rendre les choses plus claires, vous pouvez toujours ajouter un commentaire au-dessus des déclarations poilues.

// a = b + c
Complex a, b, c; a = b.add(c);
1
user14070

Alternatives à la prise en charge native de la surcharge des opérateurs Java

Puisque Java n’a pas de surcharge d’opérateurs, voici quelques alternatives que vous pouvez explorer:

  1. Utilisez une autre langue. Les deux Groovy et Scala ont des opérateurs surchargés et sont basés sur Java.
  2. Utilisez Java-oo , un plug-in qui permet la surcharge des opérateurs en Java. Notez qu'il n'est PAS indépendant de la plate-forme. En outre, il présente de nombreux problèmes et n’est pas compatible avec les dernières versions de Java (par exemple, Java 10). ( Source StackOverflow d'origine )
  3. Utilisez JNI , Java Native Interface ou des alternatives. Cela vous permet d’écrire des méthodes C ou C++ (peut-être d’autres?) À utiliser en Java. Bien sûr, cela n’est PAS indépendant de la plate-forme.

Si quelqu'un est au courant des autres, veuillez commenter, et je l'ajouterai à cette liste.

0
gagarwa

Ce n’est pas une bonne raison de la rejeter, mais une raison pratique:

Les gens ne l'utilisent pas toujours de manière responsable. Regardez cet exemple tiré de la bibliothèque Python scapy:

>>> IP()
<IP |>
>>> IP()/TCP()
<IP frag=0 proto=TCP |<TCP |>>
>>> Ether()/IP()/TCP()
<Ether type=0x800 |<IP frag=0 proto=TCP |<TCP |>>>
>>> IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
<IP frag=0 proto=TCP |<TCP |<Raw load='GET / HTTP/1.0\r\n\r\n' |>>>
>>> Ether()/IP()/IP()/UDP()
<Ether type=0x800 |<IP frag=0 proto=IP |<IP frag=0 proto=UDP |<UDP |>>>>
>>> IP(proto=55)/TCP()
<IP frag=0 proto=55 |<TCP |>>

Voici l'explication:

L'opérateur/a été utilisé comme opérateur de composition entre deux couches. Ce faisant, la couche inférieure peut avoir un ou plusieurs de ses champs par défaut surchargés selon la couche supérieure. (Vous pouvez quand même donner la valeur que vous voulez). Une chaîne peut être utilisée comme couche brute.

0
Sarien