Conjunto de métodos que amplían la funcionalidad de una clase
En programación informática , un rasgo es un concepto del lenguaje que representa un conjunto de métodos que se pueden utilizar para ampliar la funcionalidad de una clase . [1] [2]
Razón fundamental
En la programación orientada a objetos, el comportamiento a veces se comparte entre clases que no están relacionadas entre sí. Por ejemplo, muchas clases no relacionadas pueden tener métodos para serializar objetos en JSON . Históricamente, ha habido varios enfoques para resolver esto sin duplicar el código en cada clase que necesita el comportamiento. Otros enfoques incluyen la herencia múltiple y los mixins , pero estos tienen desventajas: el comportamiento del código puede cambiar inesperadamente si se altera el orden en el que se aplican los mixins o si se agregan nuevos métodos a las clases principales o mixins.
Los rasgos resuelven estos problemas al permitir que las clases utilicen el rasgo y obtengan el comportamiento deseado. Si una clase utiliza más de un rasgo, el orden en el que se utilizan los rasgos 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 , de las cuales las clases implementadoras deben proporcionar implementaciones. Al igual que un mixin, un rasgo proporciona un comportamiento adicional para la clase implementadora.
En caso de una colisión de nombres entre métodos proporcionados por diferentes características, el programador debe desambiguar explícitamente cuál de esos métodos se utilizará en la clase; de esta manera, se resuelve manualmente el problema del diamante de la herencia múltiple . Esto es diferente 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 alcance .
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
- anulación (o suma asimétrica ): una operación que forma un nuevo rasgo añadiendo métodos a un rasgo existente, posiblemente anulando algunos de sus métodos
- alias : una operación que crea un nuevo rasgo agregando un nuevo nombre para un método existente
- exclusión : operación que forma una nueva característica eliminando un método de una característica existente. (Combinar esto con la operación de alias produce una operación de cambio de nombre superficial ).
Si se excluye un método de una característica, dicho método debe ser proporcionado por la clase que consume la característica o por una clase padre de esa clase. Esto se debe a que los métodos proporcionados por la característica 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, tienen sus propias limitaciones.
Métodos necesarios
Si un rasgo requiere que la clase consumidora proporcione determinados métodos, el rasgo no puede saber si esos métodos son semánticamente equivalentes a las necesidades del rasgo. En algunos lenguajes dinámicos, como Perl, el método requerido solo se puede identificar por un nombre de método, no por una firma de método completa , lo que hace más difícil garantizar que el método requerido sea apropiado.
Métodos de exclusión
Si se excluye un método de una característica, ese método se convierte en un método "obligatorio" para la característica porque otros métodos de la característica podrían llamarlo.
Idiomas soportados
Los rasgos provienen originalmente del lenguaje de programación Self [5] y son compatibles con los siguientes 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 habilitar el estado dentro de los rasgos, lo que no estaba permitido en las primeras definiciones. [6]
- C# : Desde la versión 8.0, C# tiene soporte para 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 contenedor genéricas [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. [ cita requerida ]
- Fortaleza [12]
- Groovy : Desde la versión 2.3 [13]
- Haskell : En Haskell, los rasgos se conocen como clases de tipos .
- Haxe : Desde la versión 2.4.0. [14] Llamada Extensión Estática [15] en el manual, utiliza
using
la palabra clave - Java : Desde la versión 8, Java tiene soporte para métodos predeterminados , [16] que tienen algunas propiedades de rasgos. [17] [18] [19] [20]
- JavaScript : Los rasgos se pueden implementar a través de funciones y delegaciones [21] o mediante bibliotecas que proporcionan rasgos. [22] [23] [24]
- Julia : Varios paquetes implementan características, 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 una variedad de características del lenguaje: módulo y inclusión de tipo de módulo, funtores y tipos de funtores, clase y herencia de tipo de clase, etcétera.
- Perl : Se denominan roles y se implementan en bibliotecas de Perl como Moose , Role::Tiny y Role::Basic. Los roles son parte del lenguaje hermano Raku . [30] Con la aceptación de la propuesta OOP de Corinna [31] Perl tendrá roles nativos del lenguaje como parte de un sistema OOP 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 clase (de rasgo), como una pseudo herencia múltiple .
- Python : a través de una biblioteca de terceros, [34] [35] o a través de 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 características. [38]
- Óxido [39]
- El rasgo Scala [40] [41] está incorporado y es compatible 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 Sistema ; espacio de nombres CSharp8NewFeatures ; interfaz ILogger { // Métodos de interfaz tradicionales void Log ( string mensaje ); void LogError ( Exception excepción ); // Método de interfaz predeterminado void LogWarning ( string message ) { Console.WriteLine ( message ) ; } } clase Logger : ILogger { public void Log ( string mensaje ) { Console.WriteLine ( mensaje ) ; } public void LogError ( Excepción excepción ) { Console.WriteLine ( excepción.ToString ( ) ) ; } } clase Programa { static void Main ( string [] args ) { ILogger logger = new Logger (); logger .LogWarning ( "Algún 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 privado predeterminado y tener cuidado de no abrirlo en la clase función pública estática obtenerInstancia () { if ( null === self :: $_instance ) { self :: $_instance = new self (); } devuelve yo mismo :: $_instancia ; } }clase FrontController { usar TSingleton ; }// También se puede utilizar en clases ya extendidas class WebSite extends SomeClass { use TSingleton ; }
Esto permite simular aspectos de la herencia múltiple:
rasgo TBounding { público $x , $y , $ancho , $alto ; }rasgo TMoveable { función pública moveTo ( $x , $y ) { // … } } rasgo TResizeable { función pública redimensionar ( $newWidth , $newHeight ) { // … } } clase Rectángulo { usa 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 se expliquen los rasgos, 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 repetida de rasgos como Debug
y Ord
, la derive
macro se puede utilizar para solicitar a los compiladores que generen ciertas implementaciones automáticamente. [45] Los rasgos derivables incluyen: Clone
, Copy
, Debug
, Default
, PartialEq
, Eq
, PartialOrd
y Ord
.Hash
Véase también
Referencias
- ^ abc Schärli, Nathanael; Ducasse, Stéphane; Nierstrasz, Oscar ; Black, Andrew P. (2003). "Rasgos: Unidades componibles de comportamiento" (PDF) . Actas de la Conferencia Europea sobre Programación Orientada a Objetos (ECOOP) . Apuntes de clase en Ciencias de la Computación. 2743. Springer: 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). "Rasgos: un mecanismo para la reutilización de grano fino". 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). "Statically typed streaks" (PDF) . Universidad de Chicago . Archivado (PDF) desde el original el 17 de mayo de 2004.
- ^ Fisher, Kathleen; Reppy, John (2004). Un cálculo tipificado 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). Rasgos: un enfoque para la subclasificación por herencia múltiple . Conferencia SIGOA sobre sistemas de información de oficina. Filadelfia, Pensilvania, EE. UU.: ACM Press. pp. 1–9. doi :10.1145/966873.806468.
- ^ Van Cutsem, Tom; Bergel, Alexandre; Ducasse, Stéphane; De Meuter, Wolfgang (2009). Adición de control de estado y visibilidad a rasgos mediante anidamiento léxico (PDF) . Conferencia Europea sobre Programación Orientada a Objetos (ECOOP 2009). Apuntes de clase en Ciencias de la Computación. Vol. 5653. Springer-Verlag. págs. 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: a new and useful template technique" (Rasgos: una técnica de plantillas nueva y útil). C++ Report (Informe de C++) . Consultado 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). "Fortress Programming Language Tutorial" (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". 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). "Extensión de FeatherTrait Java con interfaces". Ciencias de la computación teórica . 398 (1–3): 243–260. doi : 10.1016/j.tcs.2008.01.051 . S2CID 12923128.
- ^ Bono, Viviana; Mensa, Enrico; Naddeo, Marco (septiembre de 2014). Trait-oriented Programming in Java 8. Conferencia internacional sobre principios y prácticas de programación en la plataforma Java: máquinas virtuales, lenguajes y herramientas (PPPJ '14). pp. 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 desde el original el 4 de agosto de 2016. Consultado el 3 de febrero de 2016 .
- ^ Seliger, Peter (11 de abril de 2014). "The Many Talents of JavaScript" (Los muchos talentos de JavaScript) . Consultado 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). "Composición de rasgos robusta para Javascript" (PDF) . Science of Computer Programming . Consultado el 23 de enero de 2016 .
- ^ "CocktailJS" . Consultado el 23 de enero de 2016 .
- ^ mauro3. «SimpleTraits.jl». GitHub . Consultado el 23 de marzo de 2017 .
{{cite web}}
: CS1 maint: numeric names: authors list (link) - ^ "Interfaces". Referencia de Kotlin . JetBrains . Consultado el 23 de enero de 2016 .
- ^ Breslav, Andrey (29 de mayo de 2015). "¡Ya salió Kotlin M12!". 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 .
- ^ "Registro de cambios de Modular Docs - Mojo🔥" docs.modular.com . Consultado el 13 de diciembre de 2023 .
- ^ chromatic (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 .
- ^ "Rasgos". Documentación 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 de mezcla de orden superior". Archivado desde el 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). «Traits in Ruby». Ruby Naseby . Consultado el 23 de enero de 2016 .
- ^ "Rasgos". 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 de Java con mucha actividad: rasgos y comportamientos". IBM developerWorks . IBM . Consultado el 23 de enero de 2016 .
- ^ "Rasgos en 10 minutos". Pharo: The CollaborActive Book . 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 .
- ^ "Rasgos - Introducción a la programación usando Rust".
- ^ "Rasgos - el lenguaje de programación Rust".
Enlaces externos
- "Rasgos: Unidades componibles de comportamiento". Grupo de composición de software . Universidad de Berna.