Trait
V programování je trait způsob návrhu použitý v objektově orientovaném programování. Trait reprezentuje kolekci metod, které mohou být použity pro rozšíření funkcionalit tříd. Velmi se podobá třídě vytvořené pouze z konkrétních metod, použitých pro rozšíření jiné třídy obdobným způsobem, jako je vícenásobné dědění. Trait však klade důraz na řešení konfliktů názvů za použití podpory samotného programovacího jazyka při následném propojování.

Traity poskytují „jednoduchý konceptuální model pro strukturu objektově orientovaného programování“ podobný mixinům. Také umožňují jednoduše vytvořit třídy, které opětovně používají chování jiné softwarové komponenty.

Charakteristika

Rozlišení mezi traitem, rozhraním a mixinem 
Traity se podobají jak rozhraní, tak mixinu. Zatímco rozhraní je tvořeno pouze názvy metod, trait obsahuje kompletní definice metod. Od rozhraní se liší také tím, že poskytuje implementaci metod, nikoli pouze jejich signaturu. Rozhraní je používáno třídou, která implementuje jeho metody. Mixin je používán třídou promícháním sebe samého a všech jeho vlastností (atributy a metody). Trait je používán třídou sloučením kolekcí extra metod poskytovaných s určitým mechanismem, který řeší konflikty názvů. Mixin obsahuje kromě definic metod také stav za pomoci proměnných, což u traitu obvykle nenalezneme.

Objekt definovaný jako trait je tedy vytvořen jako sloučenina metod, které mohou být použity jinými třídami, bez nutnosti použití vícenásobného dědění. V případě kolize jmen, kdy jeden nebo více traitů mají být použity třídou obsahující metodu stejného jména, musí programátor explicitně tento konflikt vyřešit definováním, která z metod bude v této třídě použita. Musí tedy sám vyřešit tzv. „diamantový problém“ vícenásobného dědění. Toto je rozdílné od jiných skládacích metod v objektově orientovaném programování, u nichž jsou konflikty jmen automaticky řešeny pomocí pravidel proměnných.

Zatímco mixiny mohou být použity pouze na základě dědičných operací, traity poskytují mnohem širší výběr operací:
 Symetrický součet: operace, která spojí dva rozdělené traity pro vytvoření traitu nového.
 Přepsání (asymetrický součet): operace, která vytvoří nový trait přidáním dalších metod, případně přepsáním již existujících metod existujícího traitu.
 Alias: operace, která vytvoří nový trait přidáním nového jména pro existující metodu.
 Vyloučení: operace, která vytvoří nový trait odstraněním metody z existujícího traitu. V kombinaci s operací alias získáme operaci mělké přejmenování.

Vlastnosti traitů 
 poskytují sadu metod, které implementují chování
 vyžadují sadu metod, které parametrizují poskytované chování

 trait kompozice je symetrická a konfliktní metody jsou vyloučeny z kompozice
 mohou být vnořeny, nicméně vnoření nemá žádnou sémantiku pro třídy

Vnořené traity jsou ekvivalentní flattened traitům. Abstraktní třídy jako mixiny ve vícenásobné dědičnosti programovacího jazyka Curl povolují implementaci metody a tudíž představují traity jiného jména. Modul mixiny v Ruby je do určité míry podobný traitům. Racket podporuje traity jako knihovnu a pro implementaci používá makra, struktury a first-class třídy.

Podporované jazyky 
Traity pocházejí z programovacího jazyka Self a jsou podporovány následujícími programovacími jazyky:
 Fortress: zastupují zároveň roli typů.
 Perl 5: implementováno díky Moose modulu, nazývají se „rolemi“.
 Perl 6: nazývají se rolemi a jsou součástí jazyka.
 JavaScript Delegation: fungují jako role (Traity a Mixiny)
 Squeak Smalltalk
 D: použitím __traits language extension a std.traits modulu pomocných šablon pro kompilaci časových traitů. Dostupné v D 2 od verze 2.003, s pozdější přidanou funkcionalitou. Dohromady s dalšími vlastnostmi jazyka (templety a mixiny) umožňují flexibilní automatické generování metod založených na struktuře rozhraní a typů. Jazyk D také umožňuje explicitní čištění od členských metod a proměnných, včetně přesměrování do vícero členských tříd.
 Pharo
 PHP 5.4
 Ruby: pro implementaci traitů je možno použít moduly.
 Rust
 Lasso
 Scala
 Python: použitím balíčku Traits
 Groovy: součástí od verze 2.3

Traity pro programovací jazyk Smalltalk byly původně vytvořeny skupinou Software Composition Group na Bernské univerzitě. AmbientTalk kombinuje vlastnosti ze Self traitů - objektově orientovaná vícenásobná dědičnost a Smalltalk Squeak traity, vyžadující explicitní složení traitů programátorem. AmbientTalk staví na výzkumu v oblasti stateful a freezable traitů pro umožnění stavů uvnitř traitů, což v prvních definicích nebylo umožněno.

Koncept byl aplikován jako knihovny do hlavních programovacích jazyků: C++, PHP a Javascript.

Implementace 
V počítačovém programování trait třída je třída šablona použitá k asociaci stavu a/nebo chování ke compile-time entitě, typicky datový typ nebo konstanta, bez modifikace existující entity. V C++ a PHP je běžně dosahováno definováním primární šablony třídy a vytvořením explicitních nebo částečných specializací pro relevantní typy.

Je použitá v Standard Template Library a v Standardní knihovna jazyka C pro podporu generických container třídách. Technika je značně používaná v Boost TypeTraits knihovně.

V PHP fungují traity v různých verzích odlišně. Od verze 5.4.0 je umožňěno uživatelům určit šablonu, která poskytuje možnost dědit z více než jedné (trait-)třídy jako pseudo-vícenásobná dědičnost. Traity v PHP nejsou tolik dynamické jako v C++ při používání datových typů.

Příklady

PHP 
V následujícím příkladu je použita jedna šablonová třída (trait) pro rozšíření jiné třídy:
// The template
trait TSingleton
{
    private static $_instance = null;

    public static function getInstance()
    {
        if (null === self::$_instance)
        {
            self::$_instance = new self();
        }

        return self::$_instance;
    }
}

class FrontController
{
    use TSingleton;
}

// Může být použito v již rozšířených třídách
class WebSite extends SomeClass
{
    use TSingleton;
}

To dává uživateli možnost simulovat aspekty z vícenásobné dědičnosti:
trait TBounding
{
    public $x, $y, $width, $height;
}

trait TMoveable
{
    public function moveTo($x, $y)
    {
        // ...
    }
}

trait TResizeable
{
    public function resize($newWidth, $newHeight)
    {
        // ...
    }
}

class Rectangle
{
    use TBounding, TMoveable, TResizeable;

    public function fillColor($color)
    {
        // ...
    }
}

Odkazy

Reference

Související články 
 Mixin
 Interface (programová konstrukce)

Externí odkazy 
 Generic Programming Techniques from Boost
 iterator_traits<Iterator> from SGI
 Traits: a new and useful template technique, Nathan C. Myers, C++ Report, June 1995 issue
 Traits - PHP Documentation
 Traits
 traits.js - Traits for JavaScript
 CocktailJS - ANNOTATIONS. TRAITS. TALENTS., April 2013
 The many talents of JavaScript for generalizing Role Oriented Programming approaches like Traits and Mixins, April 11, 2014

Objektově orientované programování