En programación informática , un rasgo es un concepto del lenguaje que representa un conjunto de métodos que se pueden usar para extender la funcionalidad de una clase . [ 1 ] [ 2 ]
Razón fundamental
En la programación orientada a objetos, a veces se comparte el comportamiento entre clases que no están relacionadas entre sí. Por ejemplo, muchas clases no relacionadas pueden tener métodos para serializar objetos a JSON . Históricamente, se han utilizado varios enfoques para resolver esto sin duplicar el código en cada clase que necesita dicho comportamiento. Otros enfoques incluyen la herencia múltiple y los mixins , pero estos presentan inconvenientes: el comportamiento del código puede cambiar inesperadamente si se altera el orden en que se aplican los mixins o si se agregan nuevos métodos a las clases padre o a los mixins.
Los rasgos resuelven estos problemas al permitir que las clases los utilicen y obtengan el comportamiento deseado. Si una clase usa más de un rasgo, el orden en que se usan no importa. Los métodos proporcionados por los rasgos tienen acceso directo a los datos de la clase.
Características
Los rasgos combinan aspectos de protocolos (interfaces) y mixins . Al igual que una interfaz, un rasgo define una o más firmas de métodos , cuyas implementaciones deben proporcionar las clases que lo implementan. Al igual que un mixin, un rasgo proporciona un comportamiento adicional para la clase que lo implementa.
En caso de conflicto de nombres entre métodos proporcionados por diferentes rasgos, el programador debe aclarar explícitamente cuál de esos métodos se utilizará en la clase, resolviendo así manualmente el problema del diamante de la herencia múltiple . Esto difiere de otros métodos de composición en la programación orientada a objetos, donde los nombres conflictivos se resuelven automáticamente mediante reglas de ámbito .
Las operaciones que se pueden realizar con rasgos incluyen: [ 3 ] [ 4 ]
- suma simétrica : una operación que fusiona dos rasgos disjuntos para crear un nuevo rasgo.
- sobrescritura (o suma asimétrica ): una operación que crea un nuevo rasgo añadiendo métodos a un rasgo existente, posiblemente sobrescribiendo algunos de sus métodos.
- alias : una operación que crea un nuevo rasgo añadiendo un nuevo nombre a un método existente.
- exclusión : una operación que crea un nuevo rasgo eliminando un método de un rasgo existente. (Combinar esto con la operación de alias produce una operación de cambio de nombre superficial ).
Si un método se excluye de un rasgo, dicho método debe ser proporcionado por la clase que utiliza el rasgo o por una clase padre de esa clase. Esto se debe a que los métodos proporcionados por el rasgo podrían llamar al método excluido.
La composición de rasgos es conmutativa (es decir, dados los rasgos A y B , A + B es equivalente a B + A ) y asociativa (es decir, dados los rasgos A , B y C , ( A + B ) + C es equivalente a A + ( B + C )). [ 1 ]
Limitaciones
Si bien los rasgos ofrecen ventajas significativas sobre muchas alternativas, también tienen sus propias limitaciones.
Métodos requeridos
Si una característica requiere que la clase que la utiliza proporcione ciertos métodos, la característica no puede saber si esos métodos son semánticamente equivalentes a sus necesidades. En algunos lenguajes dinámicos, como Perl, el método requerido solo se puede identificar por su nombre, no por su firma completa , lo que dificulta garantizar que el método requerido sea apropiado.
Métodos de exclusión
Si un método se excluye de una característica, ese método se convierte en un método "obligatorio" para la característica porque los otros métodos de la característica podrían llamarlo.
Idiomas compatibles
Los rasgos tienen su origen en el lenguaje de programación Self [ 5 ] y son compatibles con estos lenguajes de programación:
- AmbientTalk : Combina las propiedades de los rasgos Self (herencia múltiple basada en objetos) y los rasgos Squeak de Smalltalk (que requieren la composición explícita de rasgos por parte del programador). Se basa en la investigación sobre rasgos con estado y congelables para permitir el estado dentro de los rasgos, lo cual no estaba permitido en las primeras definiciones. [ 6 ]
- C# : Desde la versión 8.0, C# admite métodos de interfaz predeterminados , [ 7 ] que tienen algunas propiedades de rasgos. [ 8 ]
- C++ : Se utiliza en la Biblioteca de Plantillas Estándar y en la Biblioteca Estándar de C++ para admitir clases de contenedores genéricos [ 9 ] [ 10 ] y en la biblioteca Boost TypeTraits . [ 11 ]
- Curl : Las clases abstractas como mixins permiten implementaciones de métodos y, por lo tanto, constituyen rasgos con otro nombre.
- Fortaleza [ 12 ]
- Groovy : Desde la versión 2.3 [ 13 ]
- Haskell : Los rasgos se denominan clases de tipo .
- Haxe : Desde la versión 2.4.0. [ 14 ] Llamada Extensión estática [ 15 ] en el manual, utiliza
usingpalabra clave - Java : Desde la versión 8, Java admite métodos predeterminados , [ 16 ] que tienen algunas propiedades de rasgos. [ 17 ] [ 18 ] [ 19 ] [ 20 ]
- JavaScript : Los rasgos se pueden implementar mediante funciones y delegaciones [ 21 ] o a través de bibliotecas que proporcionan rasgos. [ 22 ] [ 23 ] [ 24 ]
- Julia : Varios paquetes implementan rasgos, por ejemplo, [ 25 ]
- Kotlin : Los rasgos se han denominado interfaces [ 26 ] desde M12. [ 27 ]
- Lazo [ 28 ]
- Mojo : Desde la versión 0.6.0 [ 29 ]
- OCaml : Los rasgos se pueden implementar utilizando diversas características del lenguaje: inclusión de módulos y tipos de módulos, functores y tipos de functores, herencia de clases y tipos de clases, etcétera.
- Perl : Los roles , denominados roles , se implementan en bibliotecas de Perl como Moose , Role::Tiny y Role::Basic. Los roles forman parte del lenguaje hermano Raku . [ 30 ] Con la aceptación de la Propuesta de POO de Corinna [ 31 ], Perl tendrá roles nativos del lenguaje como parte de un sistema de POO moderno.
- PHP : Desde la versión 5.4, [ 32 ] [ 33 ] PHP permite a los usuarios especificar plantillas que proporcionan la capacidad de "heredar" de más de una (trait)class, como una pseudo herencia múltiple .
- Python : Mediante una biblioteca de terceros, [ 34 ] [ 35 ] o mediante clases mixin de orden superior [ 36 ]
- Racket : Admite rasgos como una biblioteca y utiliza macros, estructuras y clases de primera clase para implementarlos. [ 37 ]
- Ruby : Los mixins de módulos se pueden usar para implementar rasgos. [ 38 ]
- Óxido [ 39 ]
- El rasgo de Scala [ 40 ] [ 41 ] es compatible de forma integrada con la palabra clave
trait. - Smalltalk : Los rasgos se implementan en dos dialectos de Smalltalk, Squeak [ 1 ] y Pharo . [ 42 ]
- Swift : Los rasgos se pueden implementar con extensiones de protocolo . [ 43 ]
Ejemplos
DO#
En C# 8.0, es posible definir una implementación como miembro de una interfaz.
usando el sistema ;espacio de nombres CSharp8NewFeatures ;interface ILogger { // Métodos de interfaz tradicionales void Log ( string message ); void LogError ( Exception exception );// Método de interfaz predeterminado void LogWarning ( string message ) { Console . WriteLine ( message ); } }clase Logger : ILogger { public void Log ( string message ) { Console . WriteLine ( message ); }public void LogError ( Exception exception ) { Console . WriteLine ( exception . ToString ()); } }public class Program { static void Main ( string [] args ) { ILogger logger = new Logger ();registrador.LogWarning ( "Mensaje de advertencia " ) ; } }PHP
Este ejemplo utiliza un rasgo para mejorar otras clases:
// El rasgo de plantilla TSingleton { private static $_instance = null ;función privada __construct () {} // Debe tener un constructor predeterminado privado y tener cuidado de no abrirlo en la clasepublic static function getInstance () { if ( null === self :: $_instance ) { self :: $_instance = new self (); }return self :: $_instance ; } }clase FrontController { usar TSingleton ; }// También se puede usar en clases ya extendidas class WebSite extends SomeClass { use TSingleton ; }Esto permite simular aspectos de la herencia múltiple:
trait TBounding { public $x , $y , $width , $height ; }trait TMoveable { public function moveTo ( $x , $y ) { // … } }trait TResizeable { public function resize ( $newWidth , $newHeight ) { // … } }clase Rectángulo { usar TBounding , TMoveable , TResizeable ;función pública fillColor ( $color ) { // … } }Óxido
Un rasgo en Rust declara un conjunto de métodos que un tipo debe implementar. [ 44 ] Los compiladores de Rust requieren que los rasgos se expliquen, lo que garantiza la seguridad de los genéricos en Rust.
// El tipo T debe tener el rasgo "Ord" // para que se puedan realizar las operaciones ">" y "<" fn max < T : Ord > ( a : & [ T ]) -> Option <& T > { let mut result = a . first () ? ; for n in a { if * n > * result { result = & n ; } } Some ( result ) }Para simplificar la implementación tediosa y repetitiva de rasgos como Debugy , se puede usar Ordla macro para solicitar a los compiladores que generen ciertas implementaciones automáticamente. [ 45 ] Los rasgos derivables incluyen: , , , , , , , y .deriveCloneCopyDebugDefaultPartialEqEqPartialOrdOrdHash
Véase también
Referencias
- 1 2 3 Schärli, Nathanael; Ducasse, Stéphane; Nierstrasz, Oscar ; Black, Andrew P. (2003). "Traits: Composable Units of Behaviour" (PDF) . Actas de la Conferencia Europea sobre Programación Orientada a Objetos (ECOOP) . Lecture Notes in Computer Science. Vol. 2743. Springer. pp. 248–274 . CiteSeerX 10.1.1.1011.8 . doi : 10.1007/978-3-540-45070-2_12 . ISBN 978-3-540-45070-2.
- ↑ Ducasse, Stéphane; Nierstrasz, Oscar; Schärli, Nathanael; Wuyts, Roel; Black, Andrew P. (marzo de 2006). "Traits: A mechanism for fine-grained reuse". ACM Transactions on Programming Languages and Systems . 28 (2): 331– 388. CiteSeerX 10.1.1.64.2480 . doi : 10.1145/1119479.1119483 . S2CID 16434119 .
- ↑ Fisher, Kathleen ; Reppy, John (2003). Rasgos tipificados estáticamente (PDF) (Informe). Universidad de Chicago . Archivado (PDF) del original el 17 de mayo de 2004.
- ↑ Fisher, Kathleen; Reppy, John (2004). Un cálculo tipado de rasgos (PDF) . 11.º Taller sobre Fundamentos de la Programación Orientada a Objetos . Universidad de Chicago .
- ↑ Curry, Gael; Baer, Larry; Lipkie, Daniel; Lee, Bruce (1982). Traits: An approach to multiple-inheritance subclassing . SIGOA Conference on Office Information Systems. Philadelphia, Pennsylvania, USA: ACM Press. pp. 1– 9. doi : 10.1145/966873.806468 .
- ↑ Van Cutsem, Tom; Bergel, Alexandre; Ducasse, Stéphane; De Meuter, Wolfgang (2009). Adding State and Visibility Control to Traits Using Lexical Nesting (PDF) . European Conference on Object-Oriented Programming (ECOOP 2009). Lecture Notes in Computer Science. Vol. 5653. Springer-Verlag. pp. 220–243 . CiteSeerX 10.1.1.372.1265 . doi : 10.1007/978-3-642-03013-0_11 . ISBN 978-3-642-03012-3.
- ↑ "Métodos de interfaz predeterminados" . Novedades de C# 8.0 . Microsoft . Consultado el 29 de noviembre de 2019 .
- ↑ "Las interfaces en C# 8.0 se renuevan" . Implementación predeterminada en Interfaces en C# 8.0 . Talking Dotnet. 9 de septiembre de 2019. Consultado el 29 de noviembre de 2019 .
- ↑ "iterator_traits < Iterator > " . Biblioteca de plantillas estándar . SGI.
- ↑ Myers, Nathan C. (junio de 1995). "Traits: una técnica de plantillas nueva y útil" . C++ Report . Recuperado el 23 de enero de 2016 .
- ↑ Abrahams, David. "Técnicas de programación genérica: rasgos" . Bibliotecas Boost C++ . Consultado el 23 de enero de 2016 .
- ↑ Steele, Guy ; Maessen, Jan-Willem (11 de junio de 2006). "Tutorial del lenguaje de programación Fortress" (PDF) . Sun Microsystems . Consultado el 23 de enero de 2016 .
- ↑ "Orientación a objetos: rasgos" . El lenguaje de programación Groovy . Consultado el 23 de enero de 2016 .
- ↑ "Haxe 2.4.0 - Haxe - El kit de herramientas multiplataforma" . Haxe - El kit de herramientas multiplataforma . Consultado el 12 de septiembre de 2017 .
- ↑ "Manual - Haxe - El kit de herramientas multiplataforma" . Haxe - El kit de herramientas multiplataforma . Consultado el 12 de septiembre de 2017 .
- ↑ "Métodos predeterminados" . Los tutoriales de Java . Oracle . Consultado el 23 de enero de 2016 .
- ↑ Liquori, Luigi; Spiwack, Arnaud (2008). "FeatherTrait: una modesta extensión de Featherweight Java" . ACM Transactions on Programming Languages and Systems . 30 (2): 11:1. doi : 10.1145/1330017.1330022 . S2CID 17231803 .
- ↑ Liquori, Luigi; Spiwack, Arnaud (2008). "Extending FeatherTrait Java with Interfaces" . Theoretical Computer Science . 398 ( 1–3 ): 243–260 . doi : 10.1016/j.tcs.2008.01.051 . S2CID 12923128 .
- ↑ Bono, Viviana; Mensa, Enrico; Naddeo, Marco (septiembre de 2014). Programación orientada a rasgos en Java 8. Conferencia internacional sobre principios y prácticas de programación en la plataforma Java: máquinas virtuales, lenguajes y herramientas (PPPJ '14) . págs. 181–6 . CiteSeerX 10.1.1.902.161 . doi : 10.1145/2647508.2647520 .
- ↑ Forslund, Emil (3 de febrero de 2016). "Definición del patrón de rasgos en Java" . Age of Java . Archivado del original el 4 de agosto de 2016. Recuperado el 3 de febrero de 2016 .
- ↑ Seliger, Peter (11 de abril de 2014). "Los muchos talentos de JavaScript" . Recuperado el 23 de enero de 2015 .
- ↑ "Traits.js: Traits para JavaScript" . Consultado el 23 de enero de 2016 .
- ↑ Van Cutsem, Tom; Miller, Mark S. (2012). "Robust Trait Composition for Javascript" (PDF) . Science of Computer Programming . Recuperado el 23 de enero de 2016 .
- ↑ "CocktailJS" . Consultado el 23 de enero de 2016 .
- ↑ Mauro Werder. "SimpleTraits.jl" . GitHub . Consultado el 23 de marzo de 2017 .
- ↑ "Interfaces" . Referencia de Kotlin . JetBrains . Consultado el 23 de enero de 2016 .
- ↑ Breslav, Andrey (29 de mayo de 2015). "¡Kotlin M12 ya está disponible!" . Blog de Kotlin . JetBrains . Consultado el 23 de enero de 2016 .
- ↑ «Rasgos» . Guía de idiomas Lasso . LassoSoft. 6 de enero de 2014 . Consultado el 23 de enero de 2016 .
- ↑ "Documentación modular - Registro de cambios de Mojo" . docs.modular.com . Consultado el 13 de diciembre de 2023 .
- ↑ cromático (30 de abril de 2009). "El porqué de los roles de Perl" . Consultado el 23 de enero de 2016 .
- ↑ Curtis "Ovid" Poe. "Propuesta de OOP de Corinna" . RFC de Corinna . Consultado el 30 de septiembre de 2022 .
- ↑ "Traits" . Documentación de PHP . The PHP Group . Consultado el 23 de enero de 2016 .
- ↑ Marr, Stefan (9 de enero de 2011). "Solicitud de comentarios: Reutilización horizontal para PHP" . Wiki de PHP.net . The PHP Group . Consultado el 31 de enero de 2011 .
- ↑ Perä, Teppo. "Documentación de py3traits" . Consultado el 23 de enero de 2016 .
- ^ Perä, Teppo (25 de marzo de 2015). "py2traits" . GitHub . Consultado el 23 de enero de 2016 .
- ↑ "Clases Mixin de Orden Superior" . Archivado del original el 9 de octubre de 2016.
- ↑ "Rasgos" . The Racket Reference . Consultado el 23 de enero de 2016 .
- ↑ David Naseby (14 de febrero de 2004). "Rasgos en Ruby" . Ruby Naseby . Consultado el 23 de enero de 2016 .
- ↑ "Traits" . El lenguaje de programación Rust . Consultado el 30 de septiembre de 2019 .
- ↑ «Rasgos» . Un recorrido por la Scala . Escuela Politécnica Federal de Lausana . Consultado el 23 de enero de 2016 .
- ↑ Neward, Ted (29 de abril de 2008). "Guía de Scala para desarrolladores Java ocupados: De rasgos y comportamientos" . IBM developerWorks . IBM . Consultado el 23 de enero de 2016 .
- ↑ "Rasgos en 10 minutos" . Pharo: El libro de CollaborActive . Consultado el 23 de enero de 2016 .
- ^ Hollemans, Matthijs (22 de julio de 2015). "Mezclas y rasgos en Swift 2.0" . Consultado el 23 de enero de 2016 .
- ↑ "Traits - Introducción a la programación con Rust" . Archivado del original el 29 de mayo de 2023.
- ↑ "Traits - el lenguaje de programación Rust" .
Enlaces externos
- "Rasgos: Unidades de comportamiento componibles" . Grupo de composición de software . Universidad de Berna.
- C++
- Temas de lenguajes de programación
- teoría de tipos