Article de reference

Trait (programmation informatique)

En programmation informatique , un trait est un concept de langage qui représente un ensemble de méthodes pouvant être utilisées pour étendre les fonctionnalités d'une classe . ...

En programmation informatique , un trait est un concept de langage qui représente un ensemble de méthodes pouvant être utilisées pour étendre les fonctionnalités d'une classe .

Raisonnement

Dans la programmation orientée objet, le comportement est parfois partagé entre des classes qui ne sont pas liées entre elles. Par exemple, de nombreuses classes non liées peuvent avoir des méthodes pour sérialiser des objets en JSON . Historiquement, il existe plusieurs approches pour résoudre ce problème sans dupliquer le code dans chaque classe nécessitant le comportement. D'autres approches incluent l'héritage multiple et les mixins , mais celles-ci présentent des inconvénients : le comportement du code peut changer de manière inattendue si l'ordre dans lequel les mixins sont appliqués est modifié, ou si de nouvelles méthodes sont ajoutées aux classes parentes ou aux mixins.

Les traits résolvent ces problèmes en permettant aux classes d'utiliser le trait et d'obtenir le comportement souhaité. Si une classe utilise plusieurs traits, l'ordre dans lequel les traits sont utilisés n'a pas d'importance. Les méthodes fournies par les traits ont un accès direct aux données de la classe.

Caractéristiques

Les traits combinent des aspects de protocoles (interfaces) et de mixins . Comme une interface, un trait définit une ou plusieurs signatures de méthode , dont les classes d'implémentation doivent fournir des implémentations. Comme un mixin, un trait fournit un comportement supplémentaire à la classe d'implémentation.

En cas de conflit de noms entre des méthodes fournies par des traits différents, le programmeur doit explicitement clarifier laquelle de ces méthodes sera utilisée dans la classe ; résolvant ainsi manuellement le problème du diamant de l'héritage multiple . Ceci est différent des autres méthodes de composition dans la programmation orientée objet, où les noms conflictuels sont automatiquement résolus par des règles de portée .

Les opérations qui peuvent être effectuées avec des traits incluent :

  • somme symétrique : opération qui fusionne deux traits disjoints pour créer un nouveau trait
  • override (ou somme asymétrique ) : une opération qui forme un nouveau trait en ajoutant des méthodes à un trait existant, en remplaçant éventuellement certaines de ses méthodes
  • alias : une opération qui crée un nouveau trait en ajoutant un nouveau nom à une méthode existante
  • exclusion : une opération qui forme un nouveau trait en supprimant une méthode d'un trait existant. (La combinaison de cette opération avec l'opération d'alias produit une opération de renommage superficielle ).

Si une méthode est exclue d'un trait, cette méthode doit être fournie par la classe qui consomme le trait ou par une classe parent de cette classe. En effet, les méthodes fournies par le trait peuvent appeler la méthode exclue.

La composition des traits est commutative (c'est-à-dire que, étant donné les traits A et B , A + B est équivalent à B + A ) et associative (c'est-à-dire que, étant donné les traits A , B et C , ( A + B ) + C est équivalent à A + ( B + C )).

Limites

Bien que les traits offrent des avantages significatifs par rapport à de nombreuses alternatives, ils ont leurs propres limites.

Méthodes requises

Si un trait requiert que la classe consommatrice fournisse certaines méthodes, le trait ne peut pas savoir si ces méthodes sont sémantiquement équivalentes aux besoins du trait. Pour certains langages dynamiques, comme Perl, la méthode requise ne peut être identifiée que par un nom de méthode, et non par une signature de méthode complète , ce qui rend plus difficile de garantir que la méthode requise est appropriée.

Hors méthodes

Si une méthode est exclue d'un trait, cette méthode devient une méthode « requise » pour le trait car les autres méthodes du trait peuvent l'appeler.

Langues prises en charge

Les traits proviennent à l'origine du langage de programmation Self et sont pris en charge par les langages de programmation suivants :

  • AmbientTalk : combine les propriétés des traits Self (héritage multiple basé sur les objets) et les traits Squeak de Smalltalk (nécessitant une composition explicite des traits par le programmeur). Il s'appuie sur la recherche sur les traits avec état et gelables pour permettre l'état au sein des traits, ce qui n'était pas autorisé dans les premières définitions.
  • C# : Depuis la version 8.0, C# prend en charge les méthodes d'interface par défaut , qui ont certaines propriétés de traits.
  • C++ : utilisé dans la bibliothèque de modèles standard et la bibliothèque standard C++ pour prendre en charge les classes de conteneurs génériques et dans la bibliothèque Boost TypeTraits.
  • Curl : Les classes abstraites comme les mixins permettent des implémentations de méthodes et constituent ainsi des traits sous un autre nom.
  • Forteresse
  • Groovy : Depuis la version 2.3
  • Haskell : En Haskell, les traits sont connus sous le nom de classes de types .
  • Haxe : Depuis la version 2.4.0. Appelée Static Extension dans le manuel, elle utilise usingle mot-clé
  • Java : Depuis la version 8, Java prend en charge les méthodes par défaut , qui possèdent certaines propriétés de traits.
  • JavaScript : Les traits peuvent être implémentés via des fonctions et des délégations ou via des bibliothèques qui fournissent des traits.
  • Julia : Plusieurs packages implémentent des traits, par exemple,
  • Kotlin : Les traits sont appelés interfaces depuis M12.
  • Lasso
  • Mojo : Depuis la version 0.6.0
  • OCaml : les traits peuvent être implémentés à l'aide de diverses fonctionnalités de langage : inclusion de modules et de types de modules, foncteurs et types de foncteurs, héritage de classes et de types de classes, etc.
  • Perl : Appelés rôles , ils sont implémentés dans les bibliothèques Perl telles que Moose , Role::Tiny et Role::Basic. Les rôles font partie du langage frère Raku . Avec l'acceptation de la proposition Corinna OOP Perl aura des rôles natifs du langage dans le cadre d'un système OOP moderne.
  • PHP : Depuis la version 5.4, PHP permet aux utilisateurs de spécifier des modèles qui offrent la possibilité « d'hériter » de plusieurs classes (de traits), comme un pseudo- héritage multiple .
  • Python : via une bibliothèque tierce, ou via des classes mixin d'ordre supérieur
  • Racket : prend en charge les traits en tant que bibliothèque et utilise des macros, des structures et des classes de première classe pour les implémenter.
  • Ruby : Les mixins de modules peuvent être utilisés pour implémenter des traits.
  • Rouille
  • Le trait Scala est intégré et pris en charge avec le mot clé trait.
  • Smalltalk : Les traits sont implémentés dans deux dialectes de Smalltalk, Squeak et Pharo .
  • Swift : Les traits peuvent être implémentés avec des extensions de protocole .

Exemples

C#

Sur C# 8.0, il est possible de définir une implémentation en tant que membre d'une interface.

en utilisant le système ;
espace de noms CSharp8NewFeatures ;
interface ILogger { // Méthodes d'interface traditionnelles void Log ( string message ); void LogError ( Exception exception );
// Méthode d'interface par défaut 
void LogWarning ( string message ) { Console . WriteLine ( message ); } }
classe Logger : ILogger { public void Log ( chaîne message ) { Console . WriteLine ( message ); }
public void LogError ( Exception exception ) { Console.WriteLine ( exception.ToString ( ) ) ; } }
classe Programme { static void Main ( string [] args ) { ILogger logger = new Logger ();
logger . LogWarning ( "Un message d'avertissement" ); 
} }

PHP

Cet exemple utilise un trait pour améliorer d’autres classes :

// Le 
trait de modèle 
TSingleton 
{ 
private 
static 
$_instance 
= 
null ;
fonction 
privée __construct () 
{} 
// Doit avoir un constructeur par défaut privé et faire attention à ne pas l'ouvrir dans la classe
fonction statique 
publique getInstance () { si ( null === self :: $_instance ) { self :: $_instance = nouveau self (); }
retourner 
self :: $_instance ; 
} 
}
classe 
FrontController 
{ 
utiliser 
TSingleton ; 
}
// Peut également être utilisé dans des classes déjà étendues 
class 
WebSite 
extends 
SomeClass 
{ 
use 
TSingleton ; 
}

Cela permet de simuler des aspects de l’héritage multiple :

trait 
TBounding 
{ 
public 
$x , 
$y , 
$largeur , 
$hauteur ; 
}
trait 
TMoveable 
{ 
public 
function 
moveTo ( $x , 
$y ) 
{ 
// … 
} 
}
trait 
TResizeable 
{ 
fonction publique 
resize ( $newWidth , $newHeight ) { // … } }
classe 
Rectangle 
{ 
utiliser 
TBounding , 
TMoveable , 
TResizeable ;
fonction 
publique fillColor ( $couleur ) 
{ 
// … 
} 
}

Rouiller

Un trait dans Rust déclare un ensemble de méthodes qu'un type doit implémenter. Les compilateurs Rust exigent que les traits soient explicités, ce qui garantit la sécurité des génériques dans Rust.

// le type T doit avoir le trait "Ord" 
// pour que les opérations ">" et "<" puissent être effectuées 
fn 
max < T : Ord > ( a : & [ T ]) -> Option <& T > { let mut result = a . first () ? ; for n in a { ​​if * n > * result { result = & n ; } } Some ( result ) }

Pour simplifier l'implémentation fastidieuse et répétée de traits comme Debuget Ord, la derivemacro peut être utilisée pour demander aux compilateurs de générer automatiquement certaines implémentations. Les traits dérivables incluent : Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ordet Hash.

Plus d articles de Worldlex Wiki

Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

Explorer l index